GOTO Can’t Die

October 7th, 2007 by peasleer

GOTO is a statement all programmers know. Most of us are too young to have ever actually used it, but anyone with a formal education has been provided with GOTO as an example of the worst enabler of ’spaghetti code.’ So after accepting that something called GOTO is bad, we return to thinking about what we’ll do after class. But why, WHY is GOTO gone?

The disappearance of GOTO can be attributed to multiple factors, most of them well presented by the famous Edsger Dijkstra back in freaking 1968 in a letter to the editor of “Communications of the ACM.” He made some humorous points, such as “the quality of programmers is a decreasing function of the density of ‘go to’ statements in the programs they produce.” Maybe I’m further gone than most (run while you can!), but it made me chuckle. The main points that he was trying to convey however are less humorous: GOTO makes it harder to ‘prove’ programs[1], removes the ability for a programmer to determine the progress of the program in execution[2], and that GOTO is just too primitive of a statement.

After some jokes among computer scientists (see COME FROM - yes, our sense of humor is in need of calibration), GOTO really did start to disappear. Most major language designs lacked official GOTO reserved words, and others like ADA included it using a syntax unique only to that statement so it may be easily found in programs. This disappearance is only surface deep, however.

It turns out that while an unbounded GOTO may result in obnoxious and nondeterministic code, the ability to jump to a segment of code outside the normal flow of execution is pretty handy. ‘Case’ statements are a popular implementation of a restricted GOTO, with one conditional evaluation resulting in a jump to one of many locations in code. More importantly, error handling would be near impossible to implement without the concepts on which GOTO was founded.

Unless the developer is an idiot, error handling is implemented as a catch in case something unexpected happens (I’ve seen it used as part of normal execution, ick). When something unexpected happens, you can no longer depend on the state of execution within the program. In this case, using a GOTO is the only way to break away from whatever caused the error and make some attempt to either rectify it or exit cleanly. Even the parody COME FROM statement has a hidden usage. In debugging, the concepts in which the COME FROM statement was founded are used to handle breakpoints.

So GOTO isn’t really dead, it is just hidden and stripped of its freedom. And more importantly, it can’t die. We rely on its concepts far too much in structured programming to do away with it. Now that you know, spread the word that GOTOs aren’t inherently bad! They are like kids: they just need boundaries.

[1] Loops and conditional statements, and of course functions, can all be reduced to formal mathematical language. Especially when converted to their recursive forms, loops are incredibly easy to prove as being valid with induction. GOTO statements broke this by making code execution able to change state at any time, greatly reducing the ease in which algorithms could be reduced to and proven with math.

[2] Some people might say “hey, loops are kind of like GOTOs. What is the difference?” Or maybe not, but here is the difference anyway. As pointed out by Dijkstra, loops are able to have some index applied to their current iteration or state in recursion (think for(int i=0; i<end; i++) - i is the index). This allows the programmer to have definite knowledge of the state of execution through using multiple indexes as “coordinates.” With a GOTO, this idea breaks because it is trivial to jump to anywhere in the program at any time, making the current indexes useless.


1 Response to “GOTO Can’t Die”

Feed for this Entry Trackback Address
  1. 1 SemaphoreLock

    GOTOs should be avoided in the general case to allow for readable code where the flow of execution is easily followed, but yeah, we shouldn’t get rid of it. Thing is, we haven’t. The try-catch statements are a specific re-tooling of GOTO, and I see the value in them (though sometimes the implementations leave something to be desired).

    GOTOs are great in heavily nested loops. They you avoid setting state variables that need to be checked as breaking conditions.

    In languages that actually allow them, that’s pretty much the only thing I find a regular use of them for. For lower level design issues they probably pop up more often, ie. the Linux kernel is totally full of them. Due to their “fall through” nature, you can save on a conditional check or two sometimes, which perhaps for embedded programming can mean big savings on a scarce resource.

    Besides, at the lowest levels, loops are GOTOs, and anyone learning real computer science should have some exposure to assembly languages, even if it is just to make them grateful for the high level abstractions we all take for granted.

    Though I admit I’m a bit of a low-level monkey. C is my favorite language, for the sheer freedom it allows you, even if it isn’t practical for many high-level or complex applications that it lacks extensive libraries for. “With great power comes great responsibility” is basically the message that should be sent when it comes to GOTOs… and C in general, really.

    GOTOs don’t work as well when your code is heavily modular, ie. you make a lot of function calls. Then we have the setjmp/longjmp stuff, which can lead to some pretty awful program “freak outs” if you do it wrong, but once again, it’s a powerful tool that, if mastered, can save people a hell of a lot of backtracking, breaking out, and returning.

Leave a Reply