Comment by adrian_b
14 hours ago
When backward jumps are allowed you can create loops that are much more tangled and incomprehensible than when you are nesting the loop structures of modern languages.
With backward jumps, you can make multiple loops that are not nested, but you could visualize them as a complex graph that has sequences of instructions in the nodes and which has multiple cycles through which the execution may or may not pass and which intersect each other. Good luck to understand how the code works, because you cannot separate parts of it that can be understood independently, like when using the "structured programming" that is ubiquitous in modern programming languages.
Such indecomposable complex multiple loops were not uncommon before 1970 in languages like FORTRAN or COBOL, and precisely this kind of control structures were the reason why the use of GOTO was criticized and considered harmful.
I said that that was a fair claim. My only point on loops is you can already get some hairy explosions with "easy" to understand loops. Since those are effectively backwards jumps already.
That said, I disagree with your idea that you can't reason about it. You are just describing a flowchart that has several arrows going in different directions. Is it as easy as a flow chart that only has arrows in one direction? Of course not. But it is doable. In fact, if you allow jumping forward out of a loop, you already have most of this.
Now, can you make one that is so complicated that it can't be understood that well? Of course you can.
I agree with your point that you can already get some hairy explosions with "easy" to understand loops.
I also agree with you that even if have not use the word "flowchart" that was what I meant, i.e. the use of unrestricted GOTO results in the most general kind of flowchart, without any constraints. I also agree that with more or less effort any flowchart, i.e. any program can be understood, but the goal of a programmer is to never make a program harder to understand than strictly necessary for solving the given problem.
My main point however, is that allowing backwards GOTO and allowing loops is not the same thing, which is the reason why Knuth in his recommendations of how to combine GOTO with structured programming and the language MESA allowed loops, but not backwards GOTO.
A loop is terminated by a backwards GOTO, but the pairs formed by the implicit label from the beginning of a loop and the backwards GOTO from the end of a loop behave like pairs of parentheses, i.e. they may only be nested and they may not be interleaved.
An arbitrary backwards GOTO does not have this restriction, i.e. it can jump in the middle of an earlier loop, which is why it can create much more complex flowcharts.
On the other hand, unlike with backwards GOTO the use of forwards GOTO makes a program more clear than any alternatives that have been proposed. For example, several languages use loop labels to enable the termination of multiple nested loops.
This is worse than with GOTO. The loop termination statement must include the label of the loop that must be terminated, e.g. it must look like "break LABEL_7" or "exit LABEL_7. This is no improvement over "goto LABEL_7".
Moreover when you try to follow the flow of control in such a program, from the loop terminating instruction you must go back, frequently to another page, because you have several levels of loops, and then from the label you must scan forward for a matching end of loop. This is significantly slower than just going from the loop terminating instruction to the point where it actually transfers the control.
On those points, I never intended a disagreement.
My only point was that in some cases it can be easier to reason with the structured steps that go to each other. Specifically, it was far easier than I expected when I started playing with that style later in life.
It was funny, as I originally put in some labeled breaks in a tight java event loop at a big company. Every wave of new employees would try to refactor into something that didn't need that. Every wave introduced a crap ton of bugs before reverting to the labeled break.
At least in that case, I granted that it was a slightly difficult part of the program to reason about. Was doable, but still difficult. What was a huge surprise to me was how much easier it was to put together a set of steps if I wasn't trying to bend them into the control structures of most programming languages.
I suspect the big thing that made this easier for me, was that you are encouraged to have the steps such that they don't jump from the middle of the step. You have what you are going to do, then you have a choice of what to do next. If you find that you wanted to jump out from the middle of a step, you break that into two steps.