Earlier quoted context omitted.
> People who give blanket rules such as never to use `goto` clearly do not understand where this idea comes from or why it should not be used. The idea comes from Dijkstra and he sure as hell did consider it a blanket rule: "I became convinced that the go to statement should be abolished from all 'higher level' programming languages (i.e. everything except, perhaps, machine code)."
C is portable machine code :)
Goto (2007)
181–190 of 207 posts
Re: Goto (2007)
#182Probably coming too late to the discussion, but commenting anyway... The issue I think is that people today read "GOTO Considered Harmful" without really understanding the world at the time. Other than simple integer FOR loops, basically all control-flow in the FORTRAN of those days was accomplished with GOTO -- and to numbered lines, not labels. Things we take for granted in all languages today like { code blocks }…
Every time this comes up, I always encourage people to read an excellent analysis by David Tribble "Go To Statement Considered Harmful: A Retrospective" that goes over Dijkstra's essay line by line and explains what it means in a more modern context: http://david.tribble.com/text/goto.html It really should be required reading in CS programs.
I've used and still use goto in the few niches it makes sense to, primarily error handling and multi-level break in C/C++.
Re: Goto (2007)
#183Earlier quoted context omitted.
> free(NULL) is not well-defined in C Oh yes it is: https://stackoverflow.com/questions/1938735/does-freeptr-whe...
I stand corrected. So, these days, null checks before free() are just for compatibility with very old systems, or more likely "tradition". I wonder where I got my wrong information? I have even seen null checks before delete in C++ code recently written by C programmers :o
It can also be a bit self-documenting, or be a place-holder if there is for example stuff to delete in a loop (elements of an array) before releasing the pointer itself (the array).
I don't know, when you read it, sometimes it feels natural and meaningful, and sometimes you know that the author didn't know that free() handles NULL all right.
Re: Goto (2007)
#184Earlier quoted context omitted.
I agree with you completely. I once made a poster (I wish I'd kept it) where I was tracing out the behaviour of a single mega function with around 50 labels in it, and gotos all over the place. I worked on a reimplementation, slowly picking apart the function into subfunctions, while loops, recursive function calls, etc. Took me about 2 weeks.
You maybe the right person to ask… Aren’t function / functioncallers a form of goto?
However, the idea behind "goto considered harmful" is almost all code can be written with function, loops and if/else statements and get just as efficient, and much, much easier to understand.
Re: Goto (2007)
#185Probably coming too late to the discussion, but commenting anyway... The issue I think is that people today read "GOTO Considered Harmful" without really understanding the world at the time. Other than simple integer FOR loops, basically all control-flow in the FORTRAN of those days was accomplished with GOTO -- and to numbered lines, not labels. Things we take for granted in all languages today like { code blocks }…
I agree with you completely. I once made a poster (I wish I'd kept it) where I was tracing out the behaviour of a single mega function with around 50 labels in it, and gotos all over the place. I worked on a reimplementation, slowly picking apart the function into subfunctions, while loops, recursive function calls, etc. Took me about 2 weeks.
If the goto graph implements a calculation with no side effects like I/O, my network will be all pure functions, too.
Completely beyond the reproach of any CS academic. :)
There is a mechanical way to do this.
1. We turn all of the function's local variables into function arguments. Each of our tail recursive functions will take these arguments.
2. Every labeled node becomes a function.
3. Every goto becomes a function call invoking the function that its target label was turned into, passing in each of its own argument to the corresponding parameter of that function. The function's return value is immediately returned.
4. Every variable assignment before a goto is turned into an argument expression in the function call which passes the new value to the corresponding argument. E.g. instead
a++; d *= 2;
goto foo;
we have return foo(a + 1, b, c, d * 2, e, ...);
Once you have this working, then you refactor. For instance, if you have a function like this: int foo(int a, int b, int c, ..., int z)
{
return a + c;
}
which does not pass its arguments to another tail-called function, then you can eliminate all of the arguments and just turn it into: int foo(int a, int c)
{
return a + c;
}
and of course edit all of the calls to foo accordingly, and simplify those places also. In this way, you will "discover" simpler functions that work with just a subset of the state transfer.Re: Goto (2007)
#186Earlier quoted context omitted.
You maybe the right person to ask… Aren’t function / functioncallers a form of goto?
Technically yes, all code eventually compiles to goto, or goto equivalents (simplifying slightly) However, the idea behind "goto considered harmful" is almost all code can be written with function, loops and if/else statements and get just as efficient, and much, much easier to understand.
What you can do with goto-based code is refactor it into a form that obeys certain conventions such that it is easy to mechanically translate to such a tail-call newtork, but then stop short of actually doing it.
Then when reading the code, just pretend you're looking at function calls.
Re: Goto (2007)
#187Probably coming too late to the discussion, but commenting anyway... The issue I think is that people today read "GOTO Considered Harmful" without really understanding the world at the time. Other than simple integer FOR loops, basically all control-flow in the FORTRAN of those days was accomplished with GOTO -- and to numbered lines, not labels. Things we take for granted in all languages today like { code blocks }…
I wonder what it would be like if kids started with BASIC. And not Visual Basic or any other modern, structured flavor. No, I mean the ancient stuff:
10 PRINT "All your base are belong to us!"
20 GOTO 10
Limited in what it can do, simple to learn, with just enough fun stuff in it (like PLOT, DRAW, INKEY$, INPUT, etc.)Then go on to assembly language, again on some very limited and simple machine, along the lines of the good old ZX Spectrum 48 or Commodore 64.
Then move on to something like C or Pascal. Or even Python and JavaScript if you want. But the idea is that going through BASIC and assembly, they'll learn two important things: 1) how computers actually work (even though it's super-simplified, it should still be useful), and 2) why you need structured programming.
Or maybe I'm just being naive. I really would like to see if that works out, though.
Re: Goto (2007)
#188Coming from assembly language, I always found the anti-goto sentiment rather cute. A beautiful restriction, but ultimately arbitrary. Like writing poetry. Or those novels that do not ever use the letter "e". Why would an otherwise sane person write code with "rep" and without ever using "jmp"?
> Or those novels that do not ever use the letter "e". As a note on this, I think the novel you're talking about is Georges Perec's 'La Disparition'. Supposedly the lack of an 'e' is symbolic of the loss of his family in the Holocaust. Anyway, I always thought one of the greatest feats of the English language was the guy who translated the novel to English, also omitting the letter 'e' . Absolutely mindblowing talent…
Unreal! I'm going to have to go read a passage or few. Thanks for mentioning it.
Re: Goto (2007)
#189Probably coming too late to the discussion, but commenting anyway... The issue I think is that people today read "GOTO Considered Harmful" without really understanding the world at the time. Other than simple integer FOR loops, basically all control-flow in the FORTRAN of those days was accomplished with GOTO -- and to numbered lines, not labels. Things we take for granted in all languages today like { code blocks }…
The first thing I do is change the indentation to reflect the structure. The basic blocks then become obvious. If you don't do that (and most people in the era didn't), it's about as hard to read as left aligned C code. With it, it's not that much harder to read than indented C code.
Unfortunately not indenting the code just reflected a bigger problem: programmers back then were totally oblivious to the structure indenting revealed or how they could be used to reduce the difficulty in reading the code: basic blocks, limited scopes and the like. It's not that they were lazy, it's that they didn't understand how code is built.
Dijkstra taught computer science. That is what he was up against. At the time, all programming languages used goto almost exclusively for flow control. In some ways, it is the simplest way to do it. One construct did the job of the multitudes we use today: for, while, until and even recursion. However if you didn't follow some simple rules the goto's invariably ended up as spaghetti and the end result ended up being there was far more spaghetti in production than structured code.
The two simple rules are: 1. backward goto's were only for loops, and 2. you must not goto inside an inner basic block. These are exact same rules for and while loops with {} blocks enforce. But it takes some self discipline to apply those rules, and no one is going to do it if they don't understand why they are important. Such understanding requires good high level intuition about how code is structured. It took a long while to teach such intuition. If you got rid of the goto's by replacing them with higher level constructs like for and while, you not only got rid of the problem - you also forced young students to think in terms of code flow. That is what Dijkstra was arguing for in "Goto's considered harmful".
Today, times have changed. You very rarely see a badly structured goto in the Linux kernel code, even though C allows it. I'm not sure why that is - because I'm pretty sure if Dijkstra hadn't won out and Javascript and it's ilk still had goto's then shudder. The coding standards in web programming is a cluster fuck as it is: I swear there isn't a week go by when I don't come up against a broken web page. Just this week I was forced to fire up the browsers js debugger to change a field on a linkedin.com form, and manually do "$0.value = 'yes'" to move on. ffs.
But yes, in projects with coding standards as high as the Linux kernels, everybody that (is allowed to?) contribute seems to have a very good understanding of how to make code that others find easy to read and understand, a ban on gotos would be counterproductive. Despite the discipline they require, gotos can be used to make the code cleaner and shorter. You see numerous examples of that in the kernel.
Re: Goto (2007)
#190Earlier quoted context omitted.
Yep, some goto uses were ostracized without ever providing the alternative. In other languages breaking numerous loops is done by naming the one you want to control: outer: for () { for () { for () { break outer;
This is much more confusing to me than just using a goto. From your example, it's not immediately clear at all to me if you're breaking out of outer, or if you're breaking TO outer. You can figure it out with this simple example, but it's way more confusing than it needs to be. And importantly: way more confusing than just using goto. Given that break and continue are just gussied up gotos anyway, just put the label…
I think it's one of the few perfectly valid uses goto.
I fully agree, but for 99% of our religious peers it is an NSFW taboo.
[1] https://www.lysator.liu.se/c/ANSI-C-grammar-y.html#labeled-s...