A while ago I needed to quote famous letter Dijkstra in 1968, and I took the opportunity to read it carefully. These days “controversy about
goto“are no longer relevant, since in most modern languages the commands
goto either it is not at all, or it is rarely used, and therefore, there is not much to discuss. However, the reasoning was interesting to me. In our area there is a mass of “folklore knowledge”, which, in practice, does not always turn out to be accurate (which is well shown in the book Bossavita), so it doesn’t hurt to evaluate Dijkstra’s logic from the point of view of today. I must say that his wording is not always easy to understand, so I decided to put them in a slightly simpler language, spending a little more space.
Letters to the editor
To begin with, we note that the genre “Go To Statement Considered Harmful” is letter to the editor magazine Communications of the ACM… That is, in front of us not scientific article, and there are no special requirements for rigor here. Most of the emails are short messages about interesting finds (including code snippets), reactions to other emails, error messages in articles, and the like. Some of them are quite funny to read. For example, one author in the same 1968 expresses dissatisfaction with hexadecimal digits. Say, if there are no AF symbols in the number, then it is unclear whether this number is decimal or hexadecimal. As a solution, he offers his own set of numbers, which looks like this:
I think I’ll flip through the letters section at my leisure, but for now, let’s get back to the main topic.
Questions of space and time
Dijkstra’s first observation is that the program exists in space and in time… When we write code, we see it as text that takes up some screen space. In the process of execution, the spatial structure fades into the background: the order of execution of instructions only partially corresponds to the original organization of the text. Further, the author notes that to track the sequence of execution of instructions in time – the task is not trivial, and it would be good to strive to reduce the “conceptual distance” between the worlds of “code in space” and “code in time”.
Now let’s discuss a small piece of code that is executed in exactly the order in which it was originally written (“in space”):
a = 5 b = 15 c = a + b # мы здесь print(c)
Suppose I am stepping through the code in the debugger, and right now I am going to run the third line. How much information is required to reproduce this situation if I need to restart the program?
Obviously, in this particular case, it is enough to set a breakpoint on the third line, and after restarting we will again find ourselves in the same state. In other words, to reproduce the state, it is enough to indicate a certain position in the code.
Branching doesn’t change this picture in any way. To get to the call
print() in the next example, I can just put a breakpoint and restart the debugger:
a = 5 b = 15 c = a + b if c == 20: print(c) # мы здесь else: pass
The situation changes as soon as function calls appear in the program. Consider the following snippet:
def f(a): c = 5 + a print(c) # мы здесь f(5) f(7)
It is no longer enough to know that the current instruction is
print()… We still need to understand which of the two calls
f() is now in progress. Thus, we need to have a complete call stack.
Similarly, when working with loops, you need to know the sequence number of the current iteration.
Why using go to is bad
At this point, it should be clear that the listed elements (current line pointers, call stacks, iteration counters) are necessary to understand what exactly happens in the program at runtime. Dijkstra emphasizes that their meanings are beyond our influence. Let’s say we can write a function or not write it, but if the function is already written, it will be used in a variety of contexts. Thus, one should simply take note of the presence of the indicated coordinates (this is the word, not “elements” used in the original article) and learn how to track their meanings.
The next step in the reasoning is already easy to do: “it becomes terribly difficult to find a meaningful set of coordinates with which to describe the progress of the process”… In other words, it is difficult to understand exactly how the program execution logic is supposed to be monitored if
go to constantly transfers control to different parts of the system.
I would not say that this argument is based on a solid scientific basis, but, probably, this is not necessary. Even if the required “set of coordinates” exists in theory, it is not easy to find and, in all likelihood, not easy to use. Dijkstra’s own conclusion is that the construction
go to “just too primitive”: we can intelligently move through something with a structure, and the ability to instantly “teleport” anywhere this structure destroys. That’s why
go to should not be used.