Is there cases where goto statement is really useful and needed?

Dear all,

Just curious, is there cases where goto statement is really useful and needed?

Yeah I mean people always saying that we need to get rid of goto.
However I found that in a case when I use MPI, If I let rank 0 to detect if some error occur, if error occur then inform all the cores to return. Then goto seems kind of inevitable.

Like the below subroutine A which contains some MPI,

subroutine A(...)
...
do i = 1, n ! all the ranks of cores are doing the do loop. 
  if ( rank ==0 ) then
! rank 0 cpu core do the job. 
! However at some point if rank 0 find error, 
! it wants to inform all the cores to return
  ... long god damn code ...
    if (detected some error) then
     quit= .true. 
     goto 100
    else
      quit = .false. 
    endif
  ...  long god damn code  ...
  endif
100 continue
  call broadcast(quit) 
! all core will wait here for rank 0 to broadcast if quit or not. 
  if (quit) then return
! if quit is true then all the cores return.
enddo
...
end subroutine A

It looks like in this case, if rank 0 detects some error, and it wants all the cores to return, I can think of the not-so-adorable goto statement is convenient. All the cores will run at 100, and wait for the broadcast, when quit is true, all the cores return subroutine A.
Is there some other way can achieve this?
I mean, if rank 0 detects something wrong, it needs to inform all the cores to stop or return or whatever.

Thanks much in advance!

PS.
This is more or less a split from the post below.

As an alternative to goto, you could use the block statement:

block1: block
    if (rank == 0) then
        ! ... long god damn code ...
        if (detected some error) then
            quit = .true.
            exit block1
        else
            quit = .false.
        end if
        ! ...  long god damn code  ...
    end if
    ! optionally: exit early here via return
end block block1

call broadcast(quit)
if (quit) return
7 Likes

Have a look at this conversation between Linus Torvalds and some other people about gotos in the Linux Kernel:

https://koblents.com/Ches/Links/Month-Mar-2013/20-Using-Goto-in-Linux-Kernel-Code/

TL;DR:
goto’s are fine in some situations

1 Like

I don’t mind gotos if they simplify the code, but in this case it’s simpler if you have two calls to broadcast and eliminate the goto and the state variable:

if (rank == 0) then
  ... long god damn code ...
  if (detected some error) then
    call broadcast(.true.)
    return
  end if
  !...  long god damn code  ...
end if
call broadcast(.false.)
2 Likes

This is actually a pattern I’ve used to get rid of alternate return from some code.

1 Like

I don’t think you even need to add a block construct, you can use a named if construct:

block1: if (rank == 0) then
    ! ... long code ...
    if (detected some error) then
        quit = .true.
        exit block1
    else
        quit = .false.
    end if
    ! ...  long code  ...
end if block1
! optionally: exit early here via return

call broadcast(quit)
if (quit) return

In cases where I see myself needing this pattern, it usually means that I should probably create a procedure for the block instead.


Just curious, is there cases where goto statement is really useful and needed?

Edit: To answer the original question, I have never come across a scenario where I have needed goto and haven’t been able to use return, cycle, or exit instead. I would be interested to hear if such a case exists.

5 Likes

Whenever you feel there is a need goto in Fortran, you are doing something wrong and you just need to modify the code, usually with case statements - and subroutines or even modules, if necessary.
The only cases I would justify the use of gotos is Assembly or a really poor (for today’s standards) “high-level” programming language. Fortran 90+ is definitely not one of them.

3 Likes

Torvalds’ comment in this case is about the Linux kernel, which is written in C, and C is not exactly a high-level programming language, but rather a “high level assembly”. From that point of view, he is right saying gotos are “fine” in some situations. However, I don’t think they are fine in modern Fortran.

2 Likes

I don’t see a significant difference in the control constructs between Fortran and C. Therefore, I don’t think it’s a matter of high or low level. As Linus said, gotos can simplify or even optimize the code. Of course, generally cycle, exit and if should be preferred, but when it fits IMHO you definitely are allowed to use goto in modern Fortran.

2 Likes

Thanks @ashe .

Uhm, broadcast(mpi bcast) is usually for rank0 to broadcast message to all the cores. However it need to act on all the cores. I mean, if only rank0 do the broadcast, call broadcast(.true.), it only broadcast to rank0 itself.
In the code above, when rank0 detect error and it will return to wherever. However all the other cores will wait there for the call broadcast(.false.), the program may hang there.
Besides, correct me if I am wrong, I do not understand what is the meaning of call broadcast(.true.) or call broadcast(.false.) . call broadcast(.true.) or call broadcast(.false.) seems does really broadcast anything. Usually there is a variable defined in all the cores. We broadcast this variable from rank0 to the same variables in all the ranks.

I do not quite see a substantial difference between goto, cycle, exit and return. In all cases there is a jump and control flow becomes obfuscated if the jump is crosses more than a few lines. Moreover, even with a properly named label it might become difficult to immediately know all the places from which a particular line can be reached.

Whenever a goto, cycle etc. might help I use logicals for the control flow. Its more verbose but readability does not suffer much or even improves slightly. Performancewise I have not seen a difference in some critical loops, where I checked different variants. I initially thought that in those cases goto will be at least slightly better…

PS: I have particularly struggled with cycle in “bigger” loops to somewhat hate this instruction…

1 Like

For anyone who thinks that GO TO has no value in modern Fortran, here is an exercise for you.

  1. Download the SLATEC distribution from netlib
    slatec

  2. Locate the file pchsp.f (for example)

  3. Now try to refactor this routine to remove ALL GO TOs particularly the ones that jump to the end of the code to write out error messages.

Hint: you can do it with some clever use of BLOCK constructs but you will not end up with anything that is in the long run more readable than just leaving the GO TOs to the error output. I put this forward as an example of one of the few remaining valid uses for GO TOs (ie jumping to code at the end of a routine to process errors and exit gracefully). Yes you can refactor it in some cases with IF and BLOCK constructs but you don’t really end up with anything thats more readable.

2 Likes

There is, quite huge. C does not provide exiting/cycling higher level constructs in nested blocks or loops. So goto might be more useful in C than in Fortran.

4 Likes