Jiwon's Encyclopedia

Why It's Bad

Modern programmers are well aware that go-to statements are bad. Introductory programming materials actively discourage and even omit, the statement altogether. It's a shortcut for spaghetti code. Why is that?

In March 1968, the famed computer scientist Edsger W. Dijkstra wrote a letter to the editor for the Communications of the ACM. It was aptly titled "Go To Statement Considered Harmful." In it, Dijkstra first distinguishes between the textual program file and the process of executing the program. He remarks that we are particularly bad at grasping the latter.

Our intellectual powers are rather geared to master static relations and that our powers to visualize processes evolving in time are relatively poorly developed. For that reason we should.....make the correspondence between the program and the process as trivial as possible.

In our program files, line numbers act as spatial indices that specify the location of a statement. On the other hand, we need a temporal index to understand the execution of code. If our program is composed of simple statements and conditional clauses, it's trivial to find said temporal index.

If the program is a pure concatenation of, say, assignment statements, it is sufficient to point in the program text to a point between two successive action descriptions......If we include conditional clauses......the fact remains that the progress of the process remains characterized by a single textual index.

If we start calling subroutines within subroutines in our program, we need a series of indices.

With the inclusion of procedures we can characterize the progress of the process via a sequence of textual indices, the length of this sequence being equal to the dynamic length of procedure calling.

If we have loops, then we can use a number to count the number of iterations we've executed so far. Anyone who's written a for loop is familiar with this concept: It's the integer i in for (int i = 0; i < max; i++).

These temporal coordinates are algorithmically generated "outside of the programmer's control." As such, by mechanically calculating the temporal index, we always know "where" the program is currently at.

If we use a lot of go-to statements in our code, however, there isn't a simple, mechanizable way to generate these temporal coordinates. The process of finding an index is manual and said index lacks semantic meaning.

The unbridled use of the go to statement has an immediate consequence that it becomes terribly hard to find a meaningful set of coordinates in which to describe the process progress.

Let's say that we have a main() function that executes 10 statements, then calls a fund() function, which then executes a loop as its first statement. Furthermore, let's say that the program is currently executing the 5th iteration of the loop. We can easily describe "where" our program is at with a coordinate: main 10, func 1 iteration 5. If the same code was implemented entirely with go-to statements, the coordinate would be some arbitrary number. The first coordinate is more semantically meaningful, and the first code easier to debug.

Go-to statements are now almost entirely replaced by structured programming methods such as conditionals and loops, pioneered by Djikstra himself.

Go-To in Finite State Machines

The other day though, I had a wild encounter with go-to statements in a textbook written in 1992. The following code implements a finite state automaton that removes 0's stuck in between 1's and vice versa. For example, the string "0000100001111011" becomes "0000000001111111".


		void bounce() {
		char x;
		/* state a */
		a: putchar('0');
		x = getchar();
		if (x == '0') goto a;
		if (x == '1') goto b;
		goto finis;
		
		/* state b */
		b: putchar('0');
		x = getchar();
		if (x == '0') goto a;
		if (x == '1') goto c;
		goto finis;
		
		/* state c */
		c: putchar('1');
		x = getchar();
		if (x == '0') goto d;
		if (x == '1') goto c;
		goto finis;
		
		/* state d */
		putchar('1');
		x = getchar();
		if (x == '0') goto a;
		if (x == '1') goto c;
		goto finis;
		
		finis: ;
		}
				

The author quite cleverly chose to use go-to statements here. In real life, programmers shouldn't hard code transitions from state to state. Instead, they can use some form of a transition table and use a variable to store the current state.

The purpose of this code, though, is to demonstrate a theoretical concept: finite state automata "jumps" from one state to another given an input character. I must say the jumping behavior of go-to statements mirror that of finite automata well. It's a clever, niche use of a relic from the past to teach a foundational concept.

Citations

  1. Edsger W. Dijkstra. 1968. Letters to the editor: go to statement considered harmful. Commun. ACM 11, 3 (March 1968), 147–148. DOI:https://doi.org/10.1145/362929.362947
  2. Al Aho and Jeff Ullman. 1994. Chapter 10 Patterns, Automata, and Regular Expressions. Foundations of Computer Science: C Edition. W. H. Freeman. http://infolab.stanford.edu/~ullman/focs.html

Šī¸ CC-BY Jiwon Chang 2021