Yeah the GOTO got a bad rap, if someone used it wrong it would have unpredicted results by goting to the wrong part of the program. It confused beginners so it was to be avoided.
People forgot that any language gets converted into assembly language and it has JMP or JUMP statements in them that basically do the same thing as a GOTO in a higher level language.
I wrote Visual BASIC 6.0 code and in order to trap errors we had a On Error Goto ErrorHandler: where we had an error handling routine that would do a customized message box to give the user more information on the error and prevent the program from ending. I would give recruiters samples of my VB code and it had On Error Goto and they saw the Goto and told me I shouldn't be using it.
VB.Net did away with Gotos and did the try/catch borrowed from Java to catch errors.
I remember learning Ada in 1989 and it used Goto statements as well. Modern Ada avoids Goto statements.
Programming without using Goto is harder and in some cases needs more lines of code.
There was never any real evidence that Goto was harmful, as the article states people accepted it was harmful without any proof. The decisions to not use Goto was decided by managers with no real world programming experience.
"GOTO considered harmful" needs to be read in its historical context, where structured programming (for loops, while loops, functions) were new-fangled and under-used.
Dijsktra was not arguing against GOTO per se, but rather against unstructured programming.
Using GOTO to implement structured programming constructs that did not exist in the language (e.g. JMP in asm) is fine.
Most reasonable programmers have understood "GOTO Considered Harmful" to be a recommendation, not a doctrine.
Goto can be very useful when used carefully, most often for a "cleanup" block, as used in the example above. It's especially common in C where the memory needs to be freed before exiting.
Obligatory Code Complete reference[1]: "These articles contain the whole goto debate. It erupts from time to time in most workplaces, textbooks, and magazines, but you won't hear anything that wasn't fully explored 20 years ago."
[1]http://www.stevemcconnell.com/ccgoto.htm
This paper talks about a certain kind of GOTOs: assembly like GOTOs that can jump anywhere in the code. GOTOs in c and c++ can only jump to a place in the current context. This makes a big difference in security and usability of GOTOs.
If your language does not give me modern control structures -- such as tail call optimization and possibly first-class continuations -- I will want goto there as a backstop. I hardly ever use it, but when I do I'll need it.
In all seriousness: only just barely. I entered the undergraduate C.S. program at the U. of Kansas in 1983. The faculty were constantly saying, "We're doing structured programming now!" -- as if they weren't quite convinced yet, and needed to remind themselves.
I think this letter does correctly point out that, while simple selection & iteration constructs are sufficient to do anything we want, concise, readable code requires more. And so now we have -- yes -- return, and also break, exceptions, etc. (I'm rather surprised that the idea of a multi-level break, which has been proposed for more than one PL, has never really caught on.)
P.S. Perhaps we could title your comment " 'GOTO Considered Harmful' Considered Harmful" Considered Harmful.
Yes. The author of the linked comment in fact complains that goto-less programming has led to the gratuitous overuse of subroutines. In the absence of modern optimizing compilers this was very inefficient.
Imagine the authors horror had he witnessed the use of properties in modern object oriented languages! Of course, properties are almost always trivial for an optimizing compiler, or a JITC, to inline, and inlining is the mother of all optimizations.
Thesis, antithesis, synthesis. The example of looking for a row of 0s that skips the current row on the first non 0 can (now) be dealt with using constructs like named break/continue statements (in things like Java or C#).
(I would not be opposed to making the inner and outer loops separate functions with returns, either, though)
What the author said was true at the time, but has since been dealt with by having richer control constructs for goto-less ("jump anywhere") programming.
It's worth noting that the coding climate has changed considerably since 1987. Modern goto-less languages, such as Java, include break and continue statements that can target any enclosing block; many of the example programs that people suggest using gotos for end up basically using these forms. It's worth pointing out that these multi-level break/continue statements allow you to build any reducible control flow graph (that is, the only thing you cannot do is construct a loop which has two entry points; incidentally, these constructs are also the best way to ensure that the optimizer gives up).
Optimizers have also gotten better over the years--it would be fairly easy to transform the idiomatic find-loop pattern based on flags to the one that uses the goto. There's also been a shift to using basic block-based optimizers, which means that the optimizer sees a loop statement and something built entirely of gotos as completely identical anyways.
So, in the end, the goto debate is moot: there's no real difference in performance either way these days, and we've renamed the goto instruction to break which sidesteps most of the puritanical section of the debate.
I wonder if anyone has done a safe form of goto that does static analysis or something to see if the jump is safe. My only experience was making error handling easier to understand.
It is rather trivial to check if a control flow is reducible (can be a platform requirement, e.g., OpenCL spec demands this). But it is unlikely that you can do too much of a static analysis with a computed goto, and the latter is the most interesting and the most useful form.
In a letter titled "On a Somewhat Disappointing Correspondence"[1][2], Dijkstra replied to this and other reponses, the larger one titled "'"GOTO Considered Harmful" Considered Harmful' Considered Harmful?" It is rather tongue in cheek.
Thanks for posting Dijkstra answer. I had read it a lot of time ago and was going to post it myself.
Even keeping in mind that it was written with tongue in cheek, Mr Dijkstra does sound like a bit of a jerk in this paper. Also, I think that this response actually validates Rubin's thesis: Dijkstra points to a number of bugs in the second and third versions of the program (i.e., those without GOTO), proving that the GOTO-less version is not only shorter, but easier to get right.
A large part of the debate that followed the publication of "GOTO Considered Harmful", and which smolders to this day, concerned whether there are any corner cases where gotos are the better choice. This rather pedantic issue is largely beside Dijkstra's main point, which was that it is infeasible to analyze programs for correctness unless they use simple, nested, control and flow structures. Of course, Dijkstra himself bears some of the responsibility for this diversion, through his choice of a click-baity title. He was probably right in this choice however, as the paper got enough attention to have a significant and lasting influence (though we are not doing analytical verification to anywhere near the extent he demanded.)
They are not corner cases, it rely depend on what domain you work in. Currently working on "tooling" for HPC application, and use goto all the time. Any form of system programming in c will probably have lots of goto's. Error handling being the most usual. Also some algos express them self best using goto's. And of course asm, try writing anything in asm without jumps :-)
I think I am on safe ground in saying that Dijkstra was well aware of the use of jumps in asm, but that is beside the point he was making in the body of the paper - as opposed to the point, taken from the title of the paper, that most of the argument has been about.
Well the part about asm was obviously a joke, control structures are nice to have. My point was that in many domains goto's are useful, both for solving problems, getting performance and for code clarity.
36 comments
[ 3.1 ms ] story [ 71.9 ms ] threadPeople forgot that any language gets converted into assembly language and it has JMP or JUMP statements in them that basically do the same thing as a GOTO in a higher level language.
I wrote Visual BASIC 6.0 code and in order to trap errors we had a On Error Goto ErrorHandler: where we had an error handling routine that would do a customized message box to give the user more information on the error and prevent the program from ending. I would give recruiters samples of my VB code and it had On Error Goto and they saw the Goto and told me I shouldn't be using it.
VB.Net did away with Gotos and did the try/catch borrowed from Java to catch errors.
I remember learning Ada in 1989 and it used Goto statements as well. Modern Ada avoids Goto statements.
Programming without using Goto is harder and in some cases needs more lines of code.
There was never any real evidence that Goto was harmful, as the article states people accepted it was harmful without any proof. The decisions to not use Goto was decided by managers with no real world programming experience.
Dijsktra was not arguing against GOTO per se, but rather against unstructured programming.
Using GOTO to implement structured programming constructs that did not exist in the language (e.g. JMP in asm) is fine.
https://github.com/golang/go/blob/master/src/strconv/atoi.go...
https://github.com/reyk/httpd/blob/master/httpd/httpd.c#L548
Goto can be very useful when used carefully, most often for a "cleanup" block, as used in the example above. It's especially common in C where the memory needs to be freed before exiting.
longjmp(BACK_TO_MAMA,1);
Never used this though.
In all seriousness: only just barely. I entered the undergraduate C.S. program at the U. of Kansas in 1983. The faculty were constantly saying, "We're doing structured programming now!" -- as if they weren't quite convinced yet, and needed to remind themselves.
I think this letter does correctly point out that, while simple selection & iteration constructs are sufficient to do anything we want, concise, readable code requires more. And so now we have -- yes -- return, and also break, exceptions, etc. (I'm rather surprised that the idea of a multi-level break, which has been proposed for more than one PL, has never really caught on.)
P.S. Perhaps we could title your comment " 'GOTO Considered Harmful' Considered Harmful" Considered Harmful.
Imagine the authors horror had he witnessed the use of properties in modern object oriented languages! Of course, properties are almost always trivial for an optimizing compiler, or a JITC, to inline, and inlining is the mother of all optimizations.
(I would not be opposed to making the inner and outer loops separate functions with returns, either, though)
What the author said was true at the time, but has since been dealt with by having richer control constructs for goto-less ("jump anywhere") programming.
Optimizers have also gotten better over the years--it would be fairly easy to transform the idiomatic find-loop pattern based on flags to the one that uses the goto. There's also been a shift to using basic block-based optimizers, which means that the optimizer sees a loop statement and something built entirely of gotos as completely identical anyways.
So, in the end, the goto debate is moot: there's no real difference in performance either way these days, and we've renamed the goto instruction to break which sidesteps most of the puritanical section of the debate.
And there is a huge performance difference between a computed `goto` implementation of a VM vs. a switch-based one.
Break is not a substitute for any of this use cases.
[1]: http://www.cs.utexas.edu/users/EWD/ewd10xx/EWD1009.PDF
[2]: http://www.cs.utexas.edu/users/EWD/transcriptions/EWD10xx/EW... (transcription)
Even keeping in mind that it was written with tongue in cheek, Mr Dijkstra does sound like a bit of a jerk in this paper. Also, I think that this response actually validates Rubin's thesis: Dijkstra points to a number of bugs in the second and third versions of the program (i.e., those without GOTO), proving that the GOTO-less version is not only shorter, but easier to get right.
https://github.com/torvalds/linux/search?utf8=%E2%9C%93&q=go...