Yeah. Absolutely unreadable. The site doesn't even override the scrolling in Javascript! Not to mention there's not a single pop-up on that site. Now, how I am supposed to know that my privacy is important to them?
Gosh, you weren't kidding. Even ignoring the painful contrast and small text, the background characters not being regular (lined-up) is setting off my ADHD something awful, I keep getting distracted, couldn't make it through the first paragraph.
To me, I use the reader mode on my browser because it allows me to have a consistent view for every article I put through it. I can have a font size, and background colour that is comfortable for me to read. I do however notice that reader modes seem to be used more so for making horrible looking websites like this readable.
It seems browser dependent, I also needed reader mode in desktop Firefox, but intrigued by your comment found it seems fine on FF Android. (In the former the background was way more disruptive, the pattern on it interfering with the text so much as to make it illegible.)
The "Goto Statement Considered Harmful" paper kinda overshot its mark, IMO.
It made perfect sense back when people were writing BASIC full of "GOTO 110" and "GOTO 520" that resulted in a tangled mess. Unfortunately it caught on so well that it resulted in people being really obsessive about it, and rejecting every single instance of it in C code, even in places where it makes perfect sense and makes the code cleaner.
Structured programming makes perfect sense in lieu of the rather silly rejection in this article that holds no more water than ‘Fortran has goto and no structured programming and that is what I’m used to’.
goto makes sense in C for cleanup of local resources. Passing a bunch of pointers to pointers to another function for cleanup makes code far less readable (jumping around in a source file instead of just reading code linearly and freeing local resources in the scope in which they were allocated). Basically, forcing structured programming over using goto is the anti-lambda — requiring a lot of jumping around in the SOURCE file (not necessarily the binary) instead of linearly scanning through the code.
Dijkstra was wrong with his “goto” paper. It’s fine to admit that. He was right about most other things.
Sure, there are uses. But they are not in this article. The article argues that without goto, an if statement can only conditionally execute one statement.
> The paper doesn't explain to us what would be the use of the "if" statement without a "goto" to redirect the flow of execution: Should all our postconditions consist of a single statement[…]?
These BASIC goto statements are pretty tame. Some basic interpreters did not require the line number in the statement to be constant. You could do things like a switch:
switch n{case 1: case 2: case 3:}
would become e.g.
goto n*100+1000
with lines 1100,1200,1300 handling the cases.
And then there was the hidden advanced troubleshooting console:
Goto in C (and worse, setjmp) is almost always a workaround for a deficiency in C. Examples:
The "goto cleanup" idiom to do deferred work (I don't like defer or finally in languages which have them, but at least these are language constructs which say what we wanted, the goto cleanup idiom only achieves that in some very easy cases, in more complicated cases your actual intent will be unclear)
The "iterator escape" idiom to get out of some larger iterative operation we're doing because we just realised we want to give up / found the overall answer. This is lack of imagination in the language's / library's / eco-system's control flow semantics and is one reason I really like Rust's core::ops::ControlFlow.
The no else statement shit drives me up the wall. Sometimes code is more readable when it says what you mean. Sometimes I want to branch, other times I want to return early. There is a difference in what I mean and code should reflect that even if the opcode is the same.
We've adopted single entry / single exit except for short functions (< 10-15 lines), where all the returns are clearly visible at once. It seemed to placate both sides, and it allows you to write that simple 'findFoo' function that returns 'foo' as soon as it finds it.
I'm one of those and rather unsure of its value. The original reason is the modelling of the program as a reducible graph (if I'm not getting confused with other stuff).
I occasionally have a couple of returns in one func but only for very, very simple and short funcs where it's clearer.
I dunno. Perhaps the problem is we're missing some higher level procedural construct - any ideas?
The 'hidden gotos', especially like an early return, for me have stricter guarantees and limitations than a goto used in the same way. Goto and labels can do too much for me to like them, i prefer more specific things with clearer boundaries and intent.
Sorry, I don't fully understand what you mean by that. Are "early returns" easier to miss when reading code (easier to miss than goto statements achieving the same effect)? If that was your intended meaning (sorry I am missing some sleep today) I don't share that view, I think both statements are equally obvious in that regard.
Examples I was thinking about:
* an early return can only go back to the call-site
* all returns in a function or method return to the same place
* an early return terminates the context it is in
* an early return does not create an entry point for nearly arbitrary other code points as labels for gotos do
It has been, literally, many decades since I last found a place where C++ code would benefit from use of a goto statement.
Those few places where they appear in (what would have been) defensible C code are better served by reliance on destructors. I.e., it is much better to start compiling the C code with a C++ compiler, and then clean it up.
> Electronic mail on the Arpanet is indeed a nice gizmo, but it is unlikely it will ever be diffused outside academic circles and public laboratories—environments in which the need to maintain confidentiality is scarcely pressing. Laboratories with military contracts will never communicate through the Arpanet! Either normal people or small companies will be able to afford a VAX each, or the market for electronic mail will remain tiny
My father witnessed an instance of this. At the early days of the Internet, he purchased a tech magazine and so he ended up talking about all the new possibilities that the Internet was offering, including emails. His friend said: "Yeah, but this things are not going to last: people will always prefer to send a fax".
Plot twist. Fax is not dead yet even in 2022. I was at the DMV and they asked for something to be faxed. Yes, faxed unless I could produce the original in front.
Maybe they're going for plausible deniability - 'yeah, that could be a faxed copy of the original, and I am receiving it over fax, so it could never be original' vs. 'this is clearly not the original'...
The irony of course is that any non-original copy of a document presented in person is a 'fax' (facsimile)!
> Either normal people or small companies will be able to afford a VAX each
Well, that is what happened. PCs were definitely as powerful as the older VAXes right around time the Internet opened for business. They just weren't running the VAX OS.
Are these real historical peer reviews, or is this fiction?
To me, the peer reviews look like something you might get from a reviewer today, but I'm certain the Einstein's performance review linked on the very top is fiction.
A side note: the GOTO paper is misunderstood by modern (non-)readers, much as the writings of Adam smith would horrify most of his contemporary advocates. At the time Dijkstra wrote it, it was common for functions to have multiple entry points as well as multiple exits (as they still do today). In addition, due to the limits of memory, the importance of the not yet named DRY principle was extreme, not for today’s reason (clarity and maintainability) but simply to use less program memory, so people would jump willy-nilly into unrelated blocks of code just to avoid writing stuff out. You can still do these things in assembly (as was common back then) but modern languages make it hard to do.
55 comments
[ 2.6 ms ] story [ 96.6 ms ] threadIt made perfect sense back when people were writing BASIC full of "GOTO 110" and "GOTO 520" that resulted in a tangled mess. Unfortunately it caught on so well that it resulted in people being really obsessive about it, and rejecting every single instance of it in C code, even in places where it makes perfect sense and makes the code cleaner.
Dijkstra was wrong with his “goto” paper. It’s fine to admit that. He was right about most other things.
> The paper doesn't explain to us what would be the use of the "if" statement without a "goto" to redirect the flow of execution: Should all our postconditions consist of a single statement[…]?
And then there was the hidden advanced troubleshooting console:
The "goto cleanup" idiom to do deferred work (I don't like defer or finally in languages which have them, but at least these are language constructs which say what we wanted, the goto cleanup idiom only achieves that in some very easy cases, in more complicated cases your actual intent will be unclear)
The "iterator escape" idiom to get out of some larger iterative operation we're doing because we just realised we want to give up / found the overall answer. This is lack of imagination in the language's / library's / eco-system's control flow semantics and is one reason I really like Rust's core::ops::ControlFlow.
Code shouldn't require imagination. Sometimes the simple and readable solution is just better.
Doing if(condition) return at the start, before it gets going often reduces indentation and how many branches you need to see at once.
But I can agree sneaky returns can bite you sometimes
I occasionally have a couple of returns in one func but only for very, very simple and short funcs where it's clearer.
I dunno. Perhaps the problem is we're missing some higher level procedural construct - any ideas?
Examples I was thinking about:
* an early return can only go back to the call-site
* all returns in a function or method return to the same place
* an early return terminates the context it is in
* an early return does not create an entry point for nearly arbitrary other code points as labels for gotos do
Those few places where they appear in (what would have been) defensible C code are better served by reliance on destructors. I.e., it is much better to start compiling the C code with a C++ compiler, and then clean it up.
- In some very performance sensitive cases. It helps you skip a bunch of extra checks or variables.
- When you need to convert recursion to iteration, but want to keep the code structure mostly intact so you don't mess up the source control history.
Nowadays I will use lambdas that return early in preference to goto. Not from fastidiousness so much as to avoid confusing the optimizer.
Poster child for reprehensible use of goto is procmail.
> Electronic mail on the Arpanet is indeed a nice gizmo, but it is unlikely it will ever be diffused outside academic circles and public laboratories—environments in which the need to maintain confidentiality is scarcely pressing. Laboratories with military contracts will never communicate through the Arpanet! Either normal people or small companies will be able to afford a VAX each, or the market for electronic mail will remain tiny
The irony of course is that any non-original copy of a document presented in person is a 'fax' (facsimile)!
Well, that is what happened. PCs were definitely as powerful as the older VAXes right around time the Internet opened for business. They just weren't running the VAX OS.
To me, the peer reviews look like something you might get from a reviewer today, but I'm certain the Einstein's performance review linked on the very top is fiction.
No
A side note: the GOTO paper is misunderstood by modern (non-)readers, much as the writings of Adam smith would horrify most of his contemporary advocates. At the time Dijkstra wrote it, it was common for functions to have multiple entry points as well as multiple exits (as they still do today). In addition, due to the limits of memory, the importance of the not yet named DRY principle was extreme, not for today’s reason (clarity and maintainability) but simply to use less program memory, so people would jump willy-nilly into unrelated blocks of code just to avoid writing stuff out. You can still do these things in assembly (as was common back then) but modern languages make it hard to do.