A Quick Intro

I needed to cite Dijkstra’s famous 1968 letter the other day, and finally had an easy chance to read it through. It would have been shame not to do it, given its modest size.

There are many "folk beliefs" in our trade, as Bossavit’s book shows, that turn out to have quite a weak foundation. Currently, the "go to debate" is not on the table at all, as most modern languages have abandoned this operation (and it is used very sparingly anyway even when it is available). Still, I was curious how exactly Dijkstra tried to make his point. It turned out to be quite an interesting reading. Since Dijkstra’s thinking isn’t always easy to follow, I decided to expand it here, using a somewhat longer and hopefully simpler language.

It should be noted that "Go To Statement Considered Harmful" is a letter to the editor. It is not a formal research paper, and does not have to be very rigorous. Actually, reading the "letters" section can be quite fun. Most letters are short notes representing comments, interesting findings, corrections of earlier papers, and responses to other authors. Occasionally, these notes can be rather peculiar. For example, one author was unhappy with the fact that hexadecimal digits overlap with our conventional decimal characters, and proposed his own set of digits that looks like this:

new hex

I feel I should explore this "blogosphere" of yesteryear a bit more, but for now let’s get back to Dijkstra’s argument.

The Matters of Space and Time

First, Dijkstra notes that a computer program exists both in space and in time. When we write code, we see it as a text spanning across some screen space. In contrast, when we run code, its spatial organization is not relevant anymore: instructions are executed in order, only partially resembling the original textual sequence. Next, the author suggests that mentally tracing operations in time is not easy, so it would be beneficial to reduce the conceptual gap between these worlds of "spatial code" and "temporal code".

How to Trace

Let’s consider some piece of code that executes in the same order as it is spread in space:

1
2
3
4
a = 5
b = 15
c = a + b # we are here
print(c)

Suppose I am tracing this code in a debugger, and currently I am about to execute the third line. How much information do I need to recreate this situation if I have to restart the program?

Obviously, in this case I simply need to set a breakpoint at line 3 to end up in the same state as before. In other words, it is sufficient to point out exactly one location in code.

Branching does not bring any changes into this picture. To arrive at the print() call in the next example, I set a breakpoint there and restart the debugger:

1
2
3
4
5
6
7
a = 5
b = 15
c = a + b
if c == 20:
    print(c) # we are here
else:
    pass

What does make the difference is function calls. Consider the following fragment:

1
2
3
4
5
6
def f(a):
	c = 5 + a
	print(c) # we are here

f(5)
f(7)

It is not enough to know that the current instruction is print() anymore. We also need to figure out whether we are dealing with the first or with the second call of f(). Thus, we need to know the complete call stack.

Similarly, we need to know the current iteration number when dealing with loops.

Why Go To is Harmful

By now it is presumably clear that we need these elements (instruction pointers, call stacks, iteration counters) to understand what’s going on in the code. Dijkstra emphasizes that their values are beyond our control. Say, we can choose whether to create or not to create a function, but once it is available, it is expected to appear in a variety of contexts. Thus, we simply have to accept the presence of such coordinates (this is the word used in the original paper instead of "elements") and learn to track their values.

The next observation is simple: with go to "it becomes terribly hard to find a meaningful set of coordinates in which to describe the process progress". In other words, with numerous go to jumps across the program it’s hard to find out how exactly we are supposed to keep track of code execution logic.

I would not say this argument is based on rock-hard evidence, but there is probably no need for it anyway. Even if such "coordinates" exist, they are arguably hard to imagine and hard to use. Dijkstra’s own conclusion is that go to is "just too primitive": we can navigate something that has a structure, but the ability to "teleport" anywhere breaks this structure immediately.