20 ms·
The History, Controversy, and Evolution of the Goto Statement [pdf]
- svat 8y agoThis is an excellent article that sets context for, and summarizes, the “goto debate”. I know modern programmers who have simply absorbed the received wisdom that “goto is terrible” and wonder why there even is/was a debate; this short and concise article should show what goto was used for. At the time Dijkstra wrote (the letter that the editor titled) "Go To Statement Considered Harmful", his proposal would have meant programming in a C-language (of course I know C didn't exist then...) without any `break` or `continue` in loops, and without `return` except at the end of a function. There are very few languages today that don't have `break` and `continue`, and in them (Lua for instance) `goto` is still used. As the article mentions, it takes much from Knuth's wonderful summarization paper “Structured Programming with Go To Statements”, and if you find this interesting you should definitely read it! https://pic.plover.com/knuth-GOTO.pdf https://pic.plover.com/knuth-GOTO.pdf (Also reprinted in his book/collection titled Literate Programming.)
- zzo38computer 8y agoGoto is good to have. With enough other flow controls you will not use goto so much, although sometimes it is best way to do, by goto. Just because it is uncommon that it will be helpful does not mean that it should be never used; sometimes it is much more clearly and cleanly than the other way which might be messy in some case. Unfortunately, JavaScript does not have a goto command (although I wrote a way in which a preprocessor could convert programs using goto, to the one without, with the restriction that you cannot jump into a block) (what else I don't like about JavaScript is automatic semicolon insertion, although that is a different problem). Of course there is the consideration of implementation, since you will have to keep track of the labels, which may be forward or backward, rather than only the nesting level stack like implementing break/continue and if/else.
- quietbritishjim 8y agoAny time I have felt the need for something like goto, I have found that need served well by a function with multiple return statements. You're right that it can't simulate jumping into a block though, but that seems like a feature to me. Also, refactoring the necessary portion of code into a function is usually an improvement in its own right. It's funny that the GP comment mentioned this but the other comments have all focused on break/continue. I suppose the backward jumps you mention are usually only served by something like break/continue. But I find that when beginners are starting to learn to program, they very often ask for something that sounds a lot like a goto, but their need is also always satisfied by a function with multiple returns (which usually involves explaining what a function is).
- int_19h 8y agoThe funny thing is, it became a cargo cult in many ways. I once worked with a guy who persistently wrote things like these in C++: do { ... if (...) break; ... } while (false); It took me a while to realize what this was about. But, basically, he invented a way to goto (so long as it was forward) without actually spelling it out. When I asked him, he gave the usual creed about how "goto is bad", and wouldn't be convinced that break is goto, especially given how he used it. Needless to say, this kind of code is actually less readable than if it were written with a goto in it, because it looks like a loop, but actually isn't one. With goto, at least it's very clear what it's for, even when there was a better way to do the same thing.
- ensiferum 8y agoIn c++ however using goto is restricted depending on whether you'd jump over declaration of objects with non-trivial types or not.
- enriquto 8y agoof course it has to be, what would you expect it to do otherwise?
- int_19h 8y agoYou can jump past declarations if you're exiting the block - it's only a problem if you're jumping past a declaration to a point where the declared object would still be visible. But the goto equivalent of this code does not require that - it would be a jump to a label after the closing brace.
- superflyguy 8y agoI've seen and use that. It's perfectly readable once you understand it's not a loop. It's handy on c, where you can't try...throw (or don't want to in c++) where you want to do a few things which you want to treat in a transaction-like manner. You would return success from the last line in the do loop and handle errors outside the loop. It's not just about mindlessly avoiding goto; it's about writing clean structured code.
- codeulike 8y agoGOTO https://news.ycombinator.com/item?id=18485597 https://news.ycombinator.com/item?id=18485597
- augustk 8y ago> There are very few languages today that don't have `break` and `continue`, and in them (Lua for instance) `goto` is still used. Oberon is one of those few "pure" structured languages where a statement sequence is never interrupted. The latest version of Oberon doesn't even have a return statement (which is also also a form of goto unless defined as the last statement of a subroutine).
- SilasX 8y agoWait, what? From my memory, the Dijkstra comment was about arbitrary jumps from Goto statements. Like, where you could jump into another function with a completely different stack state. I saved this reddit comment that said it perfectly: >>C goto is not the type of goto that Dijkstra was complaining about. It's a tamed sort of goto. The sort of goto that Dijkstra was complaining about would allow you to do things, in modern terminology, like leap from one function directly into the middle of another function, in the middle of two loops, an if clause, and three additional nested exception contexts the goto-using function doesn't have. >>That is to say, we've built so many abstractions on top of structured programming that the modern mind can barely even comprehend the sort of goto that Dijkstra had in mind. He won his point so thoroughly that structured programming is simply the water that modern-day programmer fish swim through, taking for granted. The only gotos that are permitted are ones that honor all of the structured programming criteria. And then people get all excited saying that Dijkstra was wrong, because look at how safe these goto statements are! They can't possibly catch on fire, what with all this water we're swimming in! https://www.reddit.com/r/programming/comments/8lm8p7/30_years_from_now_the_goto_will_still_be_alive/dzijde4/ https://www.reddit.com/r/programming/comments/8lm8p7/30_year...
- svat 8y agoYou can understand what Dijkstra's comment was about, by reading both the original source (https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.p...) and the responses to it (the most comprehensive being Knuth's https://homepages.cwi.nl/~storm/teaching/reader/Knuth74.pdf https://homepages.cwi.nl/~storm/teaching/reader/Knuth74.pdf). See for instance page 277 in Knuth's paper: > Comparison of Features > Of course, event indicators are not the only decent alternatives to go to statements that have been proposed. Many authors have suggested language features which provide roughly equivalent facilities, but which are expressed in terms of exit, jump-out, break or leave statements. It goes on to discuss more alternatives (at least one of which I find in fact better than the "break" and "continue" we happen to have got with C). It also mentions: > what I believe is really the most common situation in which go to statements are needed by an ALGOL or PL/I programmer, namely [a loop which is performed "n and a half times"] This is also what the linked article discusses in section 4.1, the first one under "Common uses" (http://web.sonoma.edu/users/l/luvisi/goto/goto.pdf#page=5 http://web.sonoma.edu/users/l/luvisi/goto/goto.pdf#page=5). If you restrict Dijkstra's comment to only apply to arbitrary jumps such as those into another function, then it does it a great disservice: there's no force in the argument anymore (it's a banal claim that nearly everyone always agreed with... in fact some of the languages in which goto was being debated at the time didn't even support such non-local gotos), and there would have been no controversy. It's worthwhile to consider thoughtfully the stronger claim that Dijkstra actually made (“the go to statement should be abolished from all 'higher level' programming languages (i.e., everything except, perhaps, plain machine code)”).
- MichaelMoser123 8y agojust a nitpick: it doesn't mention setjmp/longjmp in C - that is even less restricted and allows you to jump between functions. Well it is used to do something like exception handling in C; but don't do that if C and C++ got mixed as your automatic objects in C++ will not get destructed.
- praptak 8y agoFor a relatively recent problem caused by use of goto: https://en.m.wikipedia.org/?title=Goto_fail https://en.m.wikipedia.org/?title=Goto_fail
- Sniffnoy 8y agoNon-mobile link: https://en.wikipedia.org/wiki/Unreachable_code#goto_fail_bug https://en.wikipedia.org/wiki/Unreachable_code#goto_fail_bug
- zzo38computer 8y agoThat is not specific to do with a goto command itself; even if you wrote "break" instead of "goto fail", still the second one is unconditional. But either way, can easily seen that such program is not sense, so, easily to be noticed. "There are several good coding practices that could have prevented this fault from occurring, such as code reviews, the proper use of indentation or curly braces, and test coverage analysis." Yes, it is true, whether you use goto or not, whether indentation-sensitive syntax is used or not, etc.
- RustHacker 8y agoBreak is technically a goto, albeit a nicer, more well behaved version thereof.
- goto11 8y ago
- simonh 8y agoMy father wrote a BBC Basic interpreter for MS-DOS and lectured at Coventry University for a while. I remember discussing the Dijksra article with him. He agreed that goto should generally be avoided, but said he’d used them for very deep loops where a for loop would have run out of memory. That basic interpreter was written in assembler, so he was very used to managing program structure manually with no high level constructs. On early computers, and even today, sometimes there are constraints other than clarity of the code that need to be considered. Having said that, I've not used a goto statement for at least 30 years.
- n17r4m 8y agoI kinda understand the feeling your father had. I'm currently tutoring a friend and while I was reviewing a bit of code from the assignment they had written, a simple goto would halved a lot of the complexity involved. Instead I recommended a complicated flag based system that was probably unnecessary. Although goto is harmful, perhaps it should be taught again as an advanced technique once more?
- simonh 8y agoIt's a fundamental part of assembly, so I do think it's useful to be aware of it and the debate about it's use. I learned to program on MS Basic on a CP/M machine and made heavy use of GOTO. When I started learning structured programming I had a hard time understanding how program flow could work without GOTO, so GOTO was harmful to some extent because it ingrained certain expectations and habits that were palpably bad and an obstacle to learning, but probably because I learned to sue GOTO in an undisciplined way. One of the nice things about programing in Basic back in the day was you had complete access to the hardware. You could POKE a memory address and see a dot or character appear on the screen. Basic was easy to use, but closer to assembly than modern languages in some ways even though it was interpreted. BBC Basic was really nice because it had high level constructs and low level system access.
- titanix2 8y ago> Instead I recommended a complicated flag based system that was probably unnecessary. That's the trigger for me: after more than one flag and the complex states involved, I may refactor the code using goto because it can actually be a cleaner solution. Programmers need to be less dogmatic about this case.
- bjoli 8y agoFunny this should show up, since I am just in the planning stage of implementing common lisps "tagbody" in scheme. It is mentioned in the article, but not really explained. It is a neat little localised goto that is explicit. You can only jump withinthe tagbody. Why is this useful? Well, goto is a nice little primitive for some things. Tagbody is used in CL to implement the iter (and maybe loop) macro. Because sometimes all you want is unconditional jumping around :)
- AndruLuvisi 8y agoOriginal author here. Funny you should mention that. I once made an attempt to do the same. You can find it at http://web.sonoma.edu/users/l/luvisi/scheme/prog.scm http://web.sonoma.edu/users/l/luvisi/scheme/prog.scm One fun thing about this implementation is that labels can be passed to other functions, or returned from functions, and even used to jump back into functions that have already exited, since they are based on continuations. Good luck!
- bakul 8y agoIn John Reynolds "The Discovery of Continuations" paper he cites an interesting observation by Doug McIlroy: "So while van Wijngaarden said that goto's were unnecessary ... , Dijkstra stretched the point to say that goto's were inconvenient. The latter lesson stuck." Essentially Van Wijngaarden was talking about a continuation passing style, where the remainder of a program is represented as a function, so at the end of a function you always call another function and no function ever returns! Read the paper: https://homepages.inf.ed.ac.uk/wadler/papers/papers-we-love/reynolds-discoveries.pdf https://homepages.inf.ed.ac.uk/wadler/papers/papers-we-love/...
- jsrjenkins 8y agoLooking at this from an Assembler point of view, isn't everything really just a GOTO? Instruction Register + 1 = GOTO next memory location If A then B = Branch if equal = GOTO ADDR B call function = put currebt address in stack and GOTO this address, then GOTO address on stack. It seems to me that it is just GOTO all the way down. In fact there really is nothing else but Memory and GOTO. Sort of ironic that the very foundations of machine computing is not a very good idea....
- lucozade 8y ago> Sort of ironic that the very foundations of machine computing is not a very good idea.... I'm not sure anyone (knowledgable) has ever said that they are a fundamentally bad idea. The argument has always been, effectively, that they are prone to producing code that is hard to reason about. Specifically, they are prone to producing code that requires non-local reasoning. That's something that people tend to find hard. You can find variations of the same issue with such things as the actor model of threading or structured concurrency. They're all attempts to localise activity, at the expense of some power. And similarly, they almost always get translated to a more powerful, non-local construct further down the stack.
- taejo 8y ago"GOTO considered harmful" doesn't mean you should program in assembler without JMP (and without CALL, for that matter, since the ability to CALL into the middle of a function is equally problematic). All flow control is really just GOTO in the same sense that all programming languages are just assembler. By beginning of the century, most programmers had realized that this is not the case.
- goto11 8y agoYou can be sure that Dijkstra understood that control structures are implemented in terms of jumps in the underlying machine language. He probably also assumed the reader would know that.
- codeulike 8y agoGOTO https://news.ycombinator.com/item?id=18485598 https://news.ycombinator.com/item?id=18485598
- gjm11 8y agoAn observation just for fun: if you really want to, you can solve the "average of integers, terminated by 99999" problem without needing any of { goto, break, duplicated code }. Here's one way: int sum = -99999; int count = -1; int last = 0; do { scanf("%d", &last); // scanf is kinda evil but is what article uses sum += last; count += 1; } while (last != 99999); Or you can initialize sum and count to 0 and correct them after the loop instead of pre-correcting before as the code above does. This results in code that is a little longer, very marginally slower, and somewhat easier to read. (There is still a little bit of duplication there: the magic number 99999 appears twice. For this reason I would actually use break, unless required not to like some of the students in the experiment.)
- CodeArtisan 8y agoGNU C's cleanup attribute and nesting of procedures is better than GOTO in most of cases.
- jhpriestley 8y agoToo many people took the wrong lesson from Dijkstra: that typing out "goto" in your code was wrong! The point is that structured programming helps you maintain invariants in your code, and reason from the syntax alone without having to know the entire dynamic history of the code's execution. This lesson applies equally well to Angular's "watches" for example, or the heavily event-driven style seen in some Backbone applications, but these weren't spelled "goto" so people didn't notice.
- notacoward 8y agoThe statement that jumping to an error handler evolved into modern exceptions (2.4) is a bit misleading. Exceptions as we know them today have three properties. (1) The target is not necessarily known at compile time. (2) The catcher is likely not the same function as the thrower, with several other functions in between. (3) The stack is unwound as part of the throw/catch, including things like destructors. Even the uber-powerful "goto" that Dijkstra railed against didn't have these properties, let alone the tamer "goto" of modern languages like C. Personally I think (1) and (2) are reasons why exceptions are far worse than gotos, but if you're going to have them then you'd best have (3) as well. What I always find strange is people who look down their noses at code with gotos carefully used for error cleanup, but have no qualms about flinging exceptions around in their own code. I guess those who do not learn the lessons of history, etc.
- AndruLuvisi 8y agoAs I recall, my goal was merely to point out that unstructured jumps are still used for error handling. I was in no way attempting to claim that the two features are the same. I'm sorry for any confusion.
- notacoward 8y agoNo need to apologize. I didn't mean to suggest any failure of intent or diligence. The problem is only that people who have grown up in a culture of both "goto is evil" and "exceptions are free" has a poor lens through which to view the comparison. It's just one of those things that might need to be clarified in a later version as time marches on around us. In general, I found the article very well written and helpful.
- AndruLuvisi 8y agoOriginal author here. This was a handout for a computer science colloquium talk that I gave many years ago. It's fun to see this show up on Hacker News, and thank you all for not holding it to the same standard as a proper academic paper!
- svat 8y agoThanks for a great article/talk! Many people misunderstand the goto debate and I'd like to point them to the great Knuth article for a summary but I can't; it's far too long and contains a lot of implicit context of its time. Now I have something much better to, well, ask people to go to.
- MichaelMoser123 8y agoI think old style basic is very easy to learn because of goto, you can do a lot of stuff just with goto and if statements. I guess this 'goto is harmful' mantra made it much more difficult to get started with programming as you are now forced to learn more syntax before it is possible to express anything meaningful. The lack of goto has created something of an artificial barrier.
- lou1306 8y ago> you can do a lot of stuff just with goto and if statements You can do all stuff with goto and if, but then again, why should you? Initially it sounds simple, but as the complexity grows it becomes unmaintainable (especially when goto is unstructured, or non-local, such as the "On Error GoTo ..." statement). For some time, I had to fix hundred-line legacy VBA functions and it was hard (i.e. forget trying to do it without a debbugger).
- MichaelMoser123 8y agoI was talking about educational programming: you still have to teach variables, expressions, assignment, a bunch of library functions, etc. etc. The job of teaching is not being made easier if you also have to add a lot of non trivial syntax on top of that.
- tabtab 8y agoI was once in a long online debate about whether "software engineering" was about machines and math, or the human mind ("wetware"). I leaned the "wetware" direction. As a "test", I asked the machine/math side to "objectively prove" that goto's are inferior to blocks (under most circumstances). (To be fair, the machine/math side was not uniform in their view; I'm oversimplifying for brevity.) It was a fascinating debate, but ultimately degenerated into a dispute over the definition of "go to" and "block", because the boundary is actually quite fuzzy being that hybrid structures can be created. One would probably have to settle on specific existing languages first in order to compare.