Professional Documents
Culture Documents
DONALD E. KNUTH
Stanford University, Stanford, California 9~S05
A consideration of several different examples sheds new light on the problem of ereat-
ing reliable, well-structured programs that behave efficiently. This study focuses
largely on two issues: (a) improved syntax for iterations and error exits, making it
possible to write a larger class of programs clearly and efficiently without g o t o state-
ments; (b) a methodology of program design, beginning with readable and correct,
but possibly inefficient programs that are systematically transformed if necessary into
efficient and correct, but possibly less readable code. The discussion brings out op-
posing points of view about whether or not g o t o statements should be abolished;
some merit is found on both sides of this question. Fina!ly, an attempt is made to
define the true nature of structured programming, and to recommend fruitful direc-
tions for further study.
Keywords and phrases: structured programming, g o t o statements, language design,
event indicators, recursion, Boolean variables, iteration, optimization of programs,
program transformations, program manipulation systems searching, Quieksort,
efficiency
CR categories: 4.0, 4.10, 4.20, 5.20, 5.5, 6.1 (5.23, 5.24, 5.25, 5.27)
Copyright (~) 1974, Association for Computing Machinery, Inc. General permission to republish,
but not for profit, all or part of this material is granted, provided that ACM's copyright notice is
given and that reference is made to this publication, to its date of issue, and to the fact that reprint-
ing privileges were granted by permission of the Association for Computing Machinery.
Will UTOPIA 84, or perhaps we should call documentation of a program, instead of using
it NEWSPEAK, contain go to statements? At flow charts... Then I would code the pro-
gram in assembly language from the outline.
the moment, unfortunately, there isn't even Everyone liked these outlines better than
a consensus about this apparently trivial t h e flow charts I had drawn before, which
issue, and we had better not be hung up on w e r e not very neat--my flow charts had been
the question too much longer since there are nick-named "balloon-o-grams".
only ten years left. He reported that this method made programs
I will try in what follows to give a reason- easier to plan, to modify and to check out.
ably comprehensive survey of the go to When I met Schorre in 1963, he told me of
controversy, arguing both pro and con, with- his radical ideas, and I didn't believe they
out taking a strong stand one way or the would work. In fact, I suspected that it was
other until the discussion is nearly complete. really his rationalization for not finding an
In order to illustrate different uses of go t o easy way to put labels and go t o statements
statements, I will discuss many example into his META-II subset of ALGOL [84], a
programs, some of which tend to negate the language which I liked very much except for
conclusions we might draw from the others. this omission. In 1964 I challenged him to
There are two reasons why I have chosen to write a program for the eight-queens prob-
present the material in this apparently lem without using go to statements, and he
vacillating manner. First, since I have the responded with a program using recursive
opportunity to choose all the examples, I procedures and Boolean variables, very much
don't think it's fair to load the dice by select- like the program later published independ-
ing only program fragments which favor one ently by Wirth [96].
side of the argument. Second, and perhaps I was still not convinced that all go t o
most important, I tried this approach when I statements could or should be done away
lectured on the subject at UCLA in Feb- with, although I fully subscribed to Peter
ruary, 1974, and it worked beautifully: Naur's observations which had appeared
nearly everybody in the audience had the about the same time [73]. Since Naur's
illusion that I was largely supporting his or comments were the first published remarks
her views, regardless of what those views about harmful go to's, it is instructive to
were ! quote some of them here:
If you look carefully you will find that surpris-
ingly often a g o t o statement which looks back
1. ELIMINATION OF go to STATEMENTS really is a concealed for statement. And you
will be pleased to find how the clarity of the
Historical Background
algorithm improves when you insert the f o r
clause where it belongs. . . . If the purpose [of
At the I F I P Congress in 1971 I had the a programming course] is to teach ALGOLpro-
pleasure of meeting Dr. Eiichi Goto of gramming, the use of flow diagrams will do
Japan, who cheerfully complained that he more harm than good, in my opinion.
was always being eliminated. Here is the The next year we find George Forsythe
history of the subject, as far as I have been also purging go to statements from algo-
able to trace it. rithms submitted to Communications of the
The first programmer who systematically A C M (cf. [53]). Incidentally. the second
began to avoid all labels and go to state- example program at the end of the original
ments was perhaps D. V. Schorre, then of ALGOL 60 report [72] contains four go t o
UCLA. He has written the following account statements, to labels named AA, BB, CC,
of his early experiences [85]: and DD, so it is clear that the advantages of
Since the summer of 1960, I have been writing ALGOL'S control structures weren't fully
programs in outline form, using conventions of perceived in 1960.
indentation to indicate the flow of control. I In 1965, Edsger Dijkstra published the
have never found it necessary to take excep- following instructive remarks [21]:
tion to these conventions by using go state-
ments. I used to keep these outlines as original Two programming department managers from
similarly introduced other statements which more computation an.d aren't really more
provide "equally powerful" alternative ways perspicuous. Therefore, this example has
to jump. been widely quoted in defense of the go to
In other words, it seems that there is wide- statement, and it is appropriate to scrutinize
spread agreement that go to statements are the problem carefully.
harmful, yet programmers and language Let's suppose that we've been forbidden
designers still feel the need for some euphe- to use go to statements, and that we want
mism that "goes to" without saying go to. to do precisely the computation specified in
Example 1 (using the obvious expansion of
A Searching •×ampM such a for statement into assignments and
What are the reasons for this? In [52], Floyd a while iteration). If this means not only
and I gave the following example of a typical that we want the same results, but also that
program for which the ordinary capabilities we want to do the same operations in the
of w h i l e and if statements are inadequate. same order, the mission is impossible. But if
Let's suppose that we want to search a table we are allowed to weaken the conditions
A[1] . . . A[m] of distinct values, in order to just slightly, so that a relation can be tested
find where a given value x appears; if x is not twice in succession (assuming that it will
present in the table, we want to insert it as yield the same result each time, i.e., that it
an additional entry. Let's suppose further has no side-effects), we can solve the problem
that there is another array B, where B[,] as follows:
equals the number of times we have searched
Example la:
for the value A[i]. We might solve such a
problem as follows: i:=1;
w h i l e i < m a n d A[i] # x d o i :-- i + 1 ;
E x a m p l e 1: i f i > m t h e n ra : = i; A[i] : = x; B[i] ::= 0 fi;
B[i] : = B [ i ] + I ;
for i : = 1 s t e p 1 u n t i l m d o .
i f A[i] = x t h e n go t o f o u n d fi; The a n d operation used here stands for
n o t f o u n d : i : = r e + l ; m : = i; McCarthy's sequential conjunction operator
A[i] : = x; B[i] : = 0;
f o u n d : B[i] : = B [ i ] + I ; [62, p. 185]; i.e., "p a n d q" means "if p
t h e n q else false fl", so that q is not evalu-
(In the present article I shall use an ad hoc ated when p is false. Example la will do
programming language that is very similar exactly the same sequence of computations
to ALGOL60, with one exception: the symbol as Example 1, except for one extra compari-
fi is required as a closing bracket for all i f son of i with m (and occasionally one less
statements, so that begin and end aren't computation of m + 1). If the iteration in this
needed between t h e n and else. I don't while loop is performed a large number of
really like the looks of fi at the moment; but times, the extra comparison has a negligible
it is short, performs a useful function, and effect on the running time.
connotes finality, so I'm confidently hoping Thus, we can live without the go to in
that I'll get used to it. Alan Perlis has re- Example 1. But Example la is slightly less
marked that tl is a perfect example of a readable, in my opinion, as well as slightly
cryptic notation that can make program- slower; so it isn't clear what we have gained.
ming unnecessarily complicated for begin- Furthermore, if we had made Example 1
ners; yet I'm more comfortable with fi every more complicated, the trick of going to Ex-
time I write it. I still balk at spelling other ample la would no longer work. For ex-
basic symbols backwards, and so do most of ample, suppose we had inserted another
the people I know; a student's paper con- statement into the for loop, just before the
taining the code fragment "esae; c o m m e n t i f clause; then the relations i _< m and
bletch t n e m m o c ; " is a typical reaction to A[i] -- x wouldn't have been tested consecu-
this trend !) tively, and we couldn't in general have com-
There are ways to express Example 1 bined them with and.
without go to statements, but they require John Cooke told me an instructive story
B(I)
DO; M - I ; A ( I )
B ( I ) ffi 1;
-
= X; B ( I ) ffi 0; END; Efficiency
The ratio of running times (about 6 to 4 in
the first case when n is large) is rather sur-
Solution (a) is best, but since it involves a prising to people who haven't studied pro-
null iteration (with no explicit statements gram behavior carefully. Example 2 doesn't
being iterated) most people came up with look that much more efficient, but it is.
Solution (b). The instructive point is that Experience has shown (see [46], [51]) that
Solution (b) doesn't work; there is a serious most of the running time in non-IO-bound
bug which caused great puzzlement before programs is concentrated in about 3 % of the
the reason was found. Can the reader source text. We often see a short inner loop
spot the difficulty? (The answer appears on whose speed governs the overall program
page 298.) speed to a remarkable degree; speeding up
As I've said, Example 1 has often been the inner loop by 10 % speeds up everything
used to defend the go to statement. Un- by almost 10 %. And if the inner loop has 10
fortunately, however, the example is totally instructions, a moment's thought will usually
unconvincing in spite of the arguments I've cut it to 9 or fewer.
stated so far, because the method in Example My own programming style has of course
1 is almost never a good way to search an changed during the last decade, according to
array for x ! The following modification to the the trends of the times (e.g., I'm not quite so
data structure makes the algorithm much tricky anymore, and I use fewer go to's),
better: but the major change in my style has been
Example 2: due to this inner loop phenomenon. I now
look with an extremely jaundiced eye at
A[mq-1] := x; i := 1; every operation in a critical inner loop, seek-
w h i l e A[i] ~ ~cdo i := i+1; ing to modify my program and data struc-
i f i > m then m := i; B[i] := 1;
e l s e B[i] := B [ i ] + I fi;
ture (as in the change from Example 1 to
Example 2) so that some of the operations
Example 2 beats Example 1 because it can be eliminated. The reasons for this ap-
makes the inner loop considerably faster. If proach are that: a) it doesn't take long, since
we assume that the programs have been the inner loop is short; b) the payoff is real;
handcoded in assembly language, so that the and c) I can then afford to be less efficient
values of i, m, and x are kept in registers, in the other parts of my programs, which
and if we let n be the final value of i at the therefore are more readable and more easily
end of the program, Example 1 will make written and debugged. Tools are being
6n + 10 ( + 3 if not found) references to developed to make this critical-loop identifi-
memory for data and instructions on a cation job easy (see for example [46] and
typical computer, while the second program [82]).
will make only 4n + 14 (+6'if not found).• Thus. if I hadn't seen how to remove one
If, on the other hand, we assume that these of the operations from the loop in Example I
by changing to Example 2. I would probably the same viewpoint should prevail in soft-
(at least) have made the for loop run from ware engineering~ Of course I wouldn't
m to 1 instead of from 1 to m, since it's bother making such optimizations on a one-
usually easier to test for zero than to com- shot job, but when it's a question of prepar-
pare with m. And if Example 2 were really ing quality programs, I don't want to re-
critical, I would improve on it still more by strict myself to tools that deny me such
"doubling it up" so that the machine code efficiencies.
would be essentially as follows. There is no doubt that the grail of effi-
E x a m p l e 2a:
ciency leads to abuse. Programmers waste
enormous amounts of time thinking about,
A [ m + l ] : = x; i : = 1; g o t o t e s t ; or worrying about, the speed of noncritical
loop: i := i+2; parts of their programs, and these attempts
test: i f A[i] = x t h e n g o t o f o u n d fi;
i f A [ i + I ] ~ x t h e n g o t o loop fi;
at efficiency actually have a strong negative
i := i+1; impact when debugging and maintenance are
f o u n d : i f i > m t h e n m : = i; B[i] : = 1; considered. We should forget about small
e l s e B[i] : = B [ i ] + I fi; efficiencies, say about 97% of the time: pre-
Here the loop variable i increases by 2 on mature optimization is the root of all evil.
each iteration, so we need to do that opera- Yet we should not pass up our opportuni-
tion only half as often as before; the rest of ties in that critical 3 %. A good programmer
the code in the loop has essentially been will not be lulled into complacency by such
duplicated to make this work. The running reasoning, he will be wise to look carefully
time has now been reduced to about 3.5n + at the critical code; but only after that code
14.5 or 8.5n + 23.5 under our respective has been identified. It is often a mistake to
assumptions--again this is a noticeable make a priori judgments about what parts
saving in the overall running speed, if, say, of a program are really critical, since the
the average value of n is about 20, and if universal experience of programmers who
this search routine is performed a million or have been using measurement tools has been
so times in the overall program. Such loop- that their intuitive guesses fail. After work-
optimizations are not difficult to learn and, ing with such tools for seven years, I've be-
as I have said, they are appropriate in just come convinced that all compilers written
a small part of a program, yet they very from now on should be designed to provide
often yield substantial savings. (Of course if all programmers with feedback indicating
we want to improve on Example 2a still what parts of their programs are costing
more, especially for large m, we'll use a more the most; indeed, this feedback should be
sophisticated search technique; but let's supplied automatically unless it has been
ignore that issue, at the moment, since I specificMly turned off.
want to illustrate loop optimization in gen- After a programmer knows which parts of
eral, not searching in particular.) his routines are really important, a trans-
The improvement in speed from Example formation like doubling up of loops will be
2 to Example 2a is only about 12%, and worthwhile. Note that this transformation
many people would pronounce that insig- introduces go to statements--and so do
nificant. The conventional wisdom shared several other loop optimizations; I will re-
by many of today's software engineers calls turn to this point later. Meanwhile I have
for ignoring efficiency in the small; but I to admit that the presence of go to state-
believe this is simply an overreaction to the ments in Example 2a has a negative as well
abuses they see being practiced by penny- as a positive effect on efficiency; a non-
wise-and-pound-foolish programmers, who optimizing compiler will tend to produce
can't debug or maintain their "optimized" awkward code, since the contents of regis-
programs. In established engineering dis- ters can't be assumed known when a label is
ciplines a 12 % improvement, easily obtained, passed. When I computed the running times
is never considered marginal; and I believe cited above by looking at a typical compiler's
output for this example, I found that the Aim+ 1] was already invalid in the previous
improvement in performance was not quite line. Similarly, in Example 1 there van be no
as much as I had expected. range error in the for loop unless a range
error occurred earlier. It seems senseless to
Error Exits have expensive range cheeks in those parts
For simplicity I have avoided a very impor- of my programs that I know are clean.
tant issue in the previous examples, but it In this respect I should mention I-Ioare's
must now be faced. All of the programs we almost persuasive arguments to the contrary
have considered exhibit bad programming [40, p. 18]. He points out quite correctly that.
practice, since they fail to make the neces- the current practice of compiling subscript
sary check that m has not gone out of range. range checks into the machine code while a
In each case before we perform "m := i" we program is being tested, then suppressing the
should precede that operation by a test such checks during production runs, is like a sailor
as who wears his life preserver while training
on land but leaves it behind when he sails[
if m = max then go to memory overflow; On the other hand, that sailor isn't so foolish
where max is an appropriate threshold value. if life vests are extremely expensive, and if he
I left this statement out of the examples is such an excellent swimmer that the chance
since it would have been distracting, but we of needing one is quite small compared with
need to look at it now since it is another the other risks he is taking. In the foregoing
important class of go to statements: an examples we typically are much more cer-
er~vr exit. Such checks on the validity of tain that the subscripts will be in range than
data are very important, especially in soft- that other aspects of our overall program will
ware, and it seems to be the one class of go work correctly. John Coeke observes that
to's that still is considered ugly but neces- time-consuming range checks can be avoided
sary by today's leading reformers. (I wonder by a smart compiler which first compiles the
how Val Schorre has managed to avoid such checks into the program then moves them
go to's during all these years.) out of the loop. Wirth [94] and ttoare
Sometimes it is necessary to exit from [39] have pointed out that a well-designed
several levels of control, cutting across code for statement can permit even a rather
that may even have been written by other simple-minded compiler to avoid most range
programmers; and the most graceful way to checks within loops.
do this is a direct approach with a go to or I believe that range checking should be
its equivalent. Then the intermediate levels used far more often than it currently is, but
of the program can be written under the not everywhere. On the other hand I a m
assumption that nothing will go wrong. really assuming infallible hardware when I
I will return to the subject of error exits say this; surely I wouldn't want to remove
later. the parity check mechanism from the hard-
ware, even under a hypothetical assumption
Subscript Checking that it was slowing down the computation.
In the particular examples given above we Additional memory protection is necessary
can, of course, avoid testing m vs. max if to prevent m y program from harming some-
we have dynamic range-checking on all sub- one else's,and theirs from clobbering mine.
scripts o f A. But this usually aborts the M y arguments are directed towards com-
program, giving us little or no control over piled-in tests, not towards the hardware
the error recovery; so we probably want to mechanisms which are reallj~needed to en-
test m anyway. And ouch, what subscript sure reliability.
checking does to the inner loop execution
times! In Example 2, I will certainly want to Hash Coding
suppress range-checking in the while clause Now let's move on to another example, based
since its subscript can't be out of range unless on a standard hashing technique but other-
- ~ , ~ , . ~ 4 d ~ . ~ : , - " i ~ z : ~ . : ~ . ¢ ~ ! "¸¸ •
272 • DonaldE. Knuth
for each machine in place of the old-fash- weeks ago I decided to choose an algorithm
ioned structureless assemblers that still pro- at random from my books, to study its use
liferate. of go to statements. The very first example
On the other hand I'm not really un- I encountered [54, Algorithm 6.2.3C] turned
happy that MIxAL programs appear in my out to be another case where existing pro-
books, because I believe that MIXAL is a gramming languages have no good substitute
good example of a "quick and dirty assem- for go to's. In simplified form, the loop
bler", a genre of software which will always where the trouble arises can be written as
be useful in its proper role. Such an assembler follows.
is characterized by language restrictions
E x a m p l e 5:
that make simple one-pass assembly possible,
and it has several noteworthy advantages compare:
when we are first preparing programs for a i f A[i] < x
new machine: a) it is a great improvement t h e n i f L[i] # 0
t h e n i : = L[i]; g o t o compare;
over numeric machine code; b) its rules are e l s e L[i] : = j ; g o t o insert fi;
easy to state; and c) it can be implemented e l s e i f R[i] # 0
in an afternoon or so, thus getting an effi- t h e n i : = R[i]; g o t o c o m p a r e ;
cient assembler working quickly on what e l s e R[i] :-- j ; g o t o insert fi;
may be very primitive equipment. So far I fi;
insert: A[j] := x;
have implemented six such assemblers, at L[j] := 0; R[j] := 01j := j + l ;
different times in my life, for machines or
interpretive systems or microprocessors that This is part of the well-known "tree search
had no existing software of comparable and insertion" scheme, where a binary search
utility; and in each case other constraints tree is being represented by three arrays:
made it impractical for me to take the extra A[i] denotes the information stored at node
time necessary to develop a good, structured number i, and L[i], R[~] are the respective
assembler. Thus I am sure that the concept node numbers for the roots of that node's
of quick-and-dirty-assembler is useful, and left and right subtrees; e m p t y subtrees are
I'm glad to let MIXAL illustrate what one is represented by zero. The program searches
like. However, I also believe strongly that down the tree until finding an empty sub-
such languages should never be improved to tree where x can be inserted; and variable j
the point where they are too easy or too points to an appropriate place to do the
pleasant to use; one must restrict their use insertion. For convenience, I have assumed
to primitive facilities that are easy to imple- in this example that x is not already present
ment efficiently. I would never switch to a in the search tree.
two-pass process, or add complex pseudo- Example 5 has four go to statements, but
operations, macro-facilities, or even fancy the control structure is saved from obscurity
error diagnostics to such a language, nor because the program is so beautifully sym-
would I maintain or distribute such a metric between L and R. I h-low that these
language as a standard programming tool for go to statements can be eliminated by
a real machine. All such ameliorations and introducing a Boolean variable which be-
refinements should appear in a structured comes true when L[i] or R[i] is found to be
assembler. Now that the technology is zero. But I don't want to test this variable
available, we can condone unstructured in the inner loop of my program.
languages only as a bootstrap-like means to
a limited end, when there are strong eco- Systematic Elimination
nomic reasons for not implementing a better A good deal of theoretical work has been
system. addressed to the question of g o t o elimina-
tion, and I shall now try to summarize the
Tree Searching findings and to discuss their relevance.
But, I'm digressing from my subject of go t o S. C. Kleene proved a famous theorem in
elimination in higher level languages. A few 1956 [48] which says, in essence, that the set
But, in general, their technique may cause a living conditions that are much harder to
program to grow exponentially in size; and quantify.
when error exits or other recalcitrant go Probably the worst mistake any one can
to's are present, the resulting programs will make with respect to the subject of g o t o
indeed look rather like the flowchart emula- statements is to assume that "structured-
tor sketched above. programming" is achieved by writing pro-
If such automatic go to elimination grams as we always have and then elimi-
procedures are applied to badly structured nating the go to's. Most go to's shouldn't
programs, we can expect the resulting pro- be there in the first place! What we really
grams to be at least as badly structured. want is to conceive of our program in such
Dijkstra pointed this out already in [23], a way that we rarely even think about g o t o
saying: statements, because the real need for them
hardly ever arises. The language in which we
The exercise to translate an arbitrary flow express our ideas has a strong influence on
diagram more or less mechanically into a
jumpless one, however, is not to be recom- our thought processes. Therefore, Dijkstra
mended. Then the resulting flow diagram [23] asks for more new language features--
cannot be expected to be more transparent structures which encourage clear thinking--
than the original one. in order to avoid the go to's temptations to-
In other words, we shouldn't merely ward complications.
remove go to statements because it's the
fashionable thing to do; the presence or Event Indicotors
absence of go to statements is not really the The best such language feature I know has
issue. The underlying structure of the recently been proposed by C. T. Zahn
program is what counts, and we want only [102]. Since this is still in the experimental
to avoid usages which somehow clutter up stage, I will take the liberty of modifying
the program. Good structure can be expressed his "syntactic sugar" slightly, without
in FORTRAN or COBOL, or even in assembly changing his basic idea. The essential novelty
language, although less clearly and with in his approach is to introduce a new quan-
much more trouble. The real goal is to tity into programming languages, called an
formulate our programs in such a way that event indicator (not to be confused with
they are easily understood. concepts from P L / I or SIMSC~IPT). M y
Program structure refers to the way in current preference is to write his event-
which a complex algorithm is built up from driven construct in the following two general
successively simpler processes. In most forms.
situations this structure can be described
A) l o o p u n t i l (eventh or - . - or {event)s:
very nicely in terms of sequential composi- (statement list)0;
tion, conditionals, simple iterations, and repeat;
with case statements for multiway branches; t h e n (event)l = > (statement list)l;
undisciplined go to statements make pro-
gram structure harder to perceive, and they (event)~ = > (statement list)n;
fi;
are often symptoms of a poor conceptual
formulation. But there has been far too B) b e g i n u n t i l (event)l o r . . . or (event)n;
much emphasis on go to elimination instead (statement list)0;
of on the really important issues; people end;
have a natural tendency to set up all easily then ( e v e n t ) t = > ( s t a t e m e n t list)t;
understood quantitative goal like the aboli- ievent)~ = > (statement list)z;
tion of jumps, instead of working directly fi:
for a qualitative goal like good program
structure. In a similar way, many people There is also a new statement, "(event)",
have set up "zero population growth" as a which means that the designated event has
goal to be achieved, when they really desire occurred: such a statement is allowed only
i
276 • Donald E. Knuth
within (statement lisQ0 of an u n t i l con- This use of events is, in fact, semantically
struct which declares that event. equivalent to a restricted form of go t o
In form (A), (statement list)0 is executed statement, which Peter Landin discussed
repeatedly until control leaves the construct in 1965 [58] before most of us were ready to
• entirely or until one of the named events listen. Landin's device has been reformulated
occurs; in the latter case, the statement by Clint and Hoare [14] in the following
list corresponding to that event is executed. way: Labels are declared at the beginning
The behavior in form (B) is similar, except of each block, just as procedures normally
that no iteration is implied; one of the named are, and each label also has a (label body)
events must have occurred before the e n d just as a procedure has a (procedure body).
is reached. The t h e n . . , fi part may be Within the block whose heading contains
omitted when there is only one event name. such a declaration of label L, the statement
The above rules should become clear go to L according to this scheme means
after looking at what happens when Example "execute the body of L, then leave the
5 above is recoded in terms of this new fea- block". It is easy to see that this is exactly
ture: the form of control provided by Zahn's
Example 5b:
event mechanism, with the (label body)s
replaced by (statement list)s in the t h e n • • •
loop u n t i l left leaf hit or fi postlude and with (event) statements
right leaf hit: corresponding to Landin's go to. Thus,
i f A[i] < x
t h e n i f L[i] # 0 t h e n i := L[i];
Clint and Hoare would have written Ex-
else left leaf hit fi; ample 5b as follows.
else i f R[i] # 0 t h e n i := R[i];
else right leaf hit fi; w h i l e t r u e do
fi; begin label left leaf hit; L[i] := j;
repeat; label right leaf hit; R[i] := j;
t h e n left leaf hit = > L[i] := j; i f A[i] < x
right leaf hit = > R[i] := j; t h e n i f L[i] # 0 t h e n i := L[i];
fi; e l s e go t o left leaf hit fi;
A[j] := x; L[j] := 0; R[j] := 0; j := j + l ; else i f R[/] # 0 t h e n i := R[/];
else go to right leaf hit fi;
Alternatively, using a singleevent, end;
A[j] := x; L[j] := 0; R[j] := 0; j := j + l ;
Example 5c:
I believe the program reads much better in
l o o p u n t i l leaf replaced:
i f A[i] < x
Zahn's form, with the (label body)s set in
t h e n i f L[i] # 0 t h e n i := L[i] the code between that which logically
e l s e L[i] := j; leaf replaced fi; precedes and follows.
e l s e i f R[i] # 0 t h e n i := R[i] Landin also allowed his "labels" to have
e l s e R[i] := j; leaf replaced fi; parameters like any other procedures; this
fi;
repeat; is a valuable extension to Zahn's proposal,
A[j] := x; L[j] :~ O; R[j] := O; j := j + l ; so I shall use events with value parameters
in several of the examples below.
For reasons to be discussed later, Example As Zahn [102] has shown, event-driven
5b is preferable to 5c. statements blend well with the ideas of
It is important to emphasize that the first structured programming by stepwise refine-
line of the construct merely declares the ment. Thus, Examples 1 to 3 can all be cast
event indicator names, and that event into the following more abstract form, using
indicators are not conditions which are being an event "found" with an integer parameter:
tested continually; (event) statements are
simply transfers of control which the com- b e g i n u n t i l found:
piler can treat very efficiently. Thus, in search table for x and
insert it if not present;
Example 5e the statement "leaf replaced" end;
is essentially a go to which jumps out of t h e n found (integer j) = > B[j] := B [ j ] + I ;
the loop. fi;
Thus, each'event corresponds to a particular specified block of code, and the block may
set of assertions about the state of the be dynamically respecified.
program, and the code which follows that Some people have suggested to me that
event takes cognizance of these assertions, events should be called "conditions" instead,
which are rather different from the assertions by analogy with Boolean expressions. How-
in the main body of the construct. (For this ever, that terminology would tend to imply a
reason I prefer Example 5b to Example 5c.) relation which is continually being moni-
Language features allowing multiple exits tored, instead of a happening. By writing
have been proposed by G. V. Bochmann [7], "loop u n t i l yprime is near y: . . . " we seem
and independently by Shigo et al. [86]. These to be saying that the machine should keep
are semantically equivalent to Zahn's pro- track of whether or not y and yprime are
posals, with minor variations; but they nearly equal; a better choice of words would
express such semantics in terms of state- be an event name like "loop u n t i l con-
ments that say "exit to (label)". I believe vergence established:.-." so that we can
Zahn's idea of event indicators is an im- write " i f abs(yprime - y) < epsilon X y
provement on the previous schemes, because t h e n convergence established". An event
the specification of events instead of labels occurs when the program has discovered
encourages a better conception of the pro- that the state of computatioD has changed.
gram. The identifier given to a label is often
an imperative verb like "insert" or "com- Simple Iterations
pare", saying what action is to be done next, So far I haven't mentioned what I believe
while the appropriate identifier for an event is really the most common situation in which
is more likely to be an adjective like "found". go to statements are needed by an ALGOL
The names of .events are very much like the or P L / I programmer, namely a simple
names of Boolean variables, and I believe iterative loop with one entrance and one
this accounts for the popularity of Boolean exit. The iteration statements most often
variables as documentation aids, in spite of proposed as alternatives to go to statements
their inefficiency. have been "while B do S" and "repeat S
Putting this another way, it is much u n t i l B". However, in practice, the itera-
better from a psychological standpoint to tions I encounter very often have the form
write
A: S;
loop untll found • • • ; found; ••• repeat i f B t h e n go t o Z fi;
T; go t o A;
than to write Z:
search: while true do where S and T both represent reasonably
begin ... ; leave search; .-. end.
long sequences of code. If S is empty, we
The l e a v e or e x i t statement is operationally have a while loop, and if T is empty we
the same, but intuitively different, since it have a repeat loop, but in the general case
talks more about the program than about it is a nuisance to avoid the go to state-
the problem. ments.
The P L / I language allows programmer- A typical example of such an iteration
defined ON-conditions, which are similar occurs when S is the code to acquire or
in spirit to event indicators. A programmer generate a new piece of data, B is the test
first executes a statement "ON CONDITION for end of data, and T is the processing of
(identifier) block" which specifies a block that data. Another example is when the code
of code that is to be executed when the preceding the loop sets initial conditions
identified event occurs, and an occurrence for some iterative process; then S is a com-
of that event is indicated by writing SIG- putation of quantities involved in the test
NAL CONDITION (identifier). However, for convergence, B is the test for conver-
the analogy is not very close, since control gence, and T is the adjustment of variables
returns to the statement following the for the next iteration.
SIGNAL statement after execution of the Dijkstra [29] aptly named this a loop
which is performed "n and a half times". our language would provide a single feature
The usual practice for avoiding go to's in which covered all simple iterations without
such loops is either to duplicate the code going to a rather "big" construct like the
for S, writing event-driven scheme. When a programmer
uses the simpler feature he is thereby making
S; while B do begin T; S end; it clear that he has a simple iteration, with
where B is the negation of relation B; or to exactly one condition which is being tested
figure out some sort of "inverse" for T so exactly once each time around the loop.
that "T-i; T" is equivalent to a null state- Furthermore, by providing special syntax
ment, and writing for this common case we make it easier for a
compiler to produce more efficient code,
T-l; repeat T; S u n t i l B; since the compiler can rearrange the machine
or to duplicate the code for B and to make a instructions so that the test appears physi-
redundant test, writing cally at the end of loop. (Many hours of
computer time are now wasted each day
repeat S; i f B then T fi; until B; executing unconditional jumps to the be-
or its equivalent. The reader who studies ginning of loops.)
go to-less programs as they appear in the Ole-Johan Dahl has recently proposed a
literature will find that all three of these syntax which I think is the first real solution
rather unsatisfactory constructions are used to the n -{- ~ problem, He suggests writing
frequently. the general simple iteration defined above as
I discussed this weakness of ALGOL in a
loop; S; while B: T; repeat;
letter to Niklaus Wirth in 1967, and he
proposed two solutions to the problem, where, as before, S and T denote sequences
together with many other instructive ideas of one or more statements separated by
in an unpublished report on basic concepts semicolons. Note that as in two of our
of programming languages [94]. His first original go to-free examples, the syntax
suggestion was to write refers to condition B which represents
repeat begin S; when B exit; T; end; staying in the iteration, instead of condition
B which represents exiting; and this may
and readers who remember 1967 will also be the secret of its success.
appreciate his second suggestion, Dahl's syntax may not seem appropriate
turn on begin S; when B drop out; T; end. at first, but actually it reads well in every
example I have tried, and I hope the reader
Neither set of delimiters was felt to be will reserve judgment until seeing the ex-
quite right, but a modification of the first amples in the rest of this paper. One of the
proposal (allowing one or more single-level nice properties of his syntax is that the word
exit statements within repeat b e g i n . . . repeat occurs naturally at the end of a loop
end) was later incorporated into an experi- rather than at its beginning, since we read
mental version of the ALGOL W language. the actions of the program sequentially.
Other languages such as BCPL and BLISS As we reach the end, we are instructed to
incorporated and extended the exit idea, as repeat the loop, instead of being informed
mentioned above. Zahn's construction now that the text of the loop (not its execution)
allows us to write, for example, has ended. Furthermore, the above syntax
loop until all data exhausted: avoids ALGOL'S use of the word do (and
S; also the more recent unnatural delimiter
if B then all data exhausted fi; od); the word do as used in ALGOL has
T; never sounded quite right to native speakers
repeat;
of English, it has always been rather quaint
and this is a better syntax for the n + for us to say "do read (A[i])" or "do begln"!
problem than we have had previously. Another feature of Dahl's proposals is that
On the other hand, it would be nicest if it is easily axiomatized along the lines
ments. When procedure calls occur in an above simplification makes q resume the
inner loop the overhead can slow a program caller of p. When q ffi p the argument is
down by a factor of two or more. But if we perhaps a bit subtle, but it's all right. (I'm
hand tailor our own implementation of not sure who originated this principle; I
recursion instead of relying on a general recall learning it from Gill's paper [34, p.
mechanism we can usually find worthwhile 183], and then seeing many instances of it in
simplifications, and in the process we occa- connection with top-do~vn compiler organiza-
sionally get a deeper insight into the original tion. Under certain conditions the BLms/ll
algorithm. compiler [101] is capable of discovering this
There has been a good deal published simplification. Incidentally, the converse of
about recursion elimination (especially in the the above principle is also true (see [52]):
work of Barron [4], Cooper [15], Manna and go to statements can always be eliminated
Waldinger [61], McCarthy [62], and Strong by declaring suitable procedures, each of
[88; 91]); but I'm amazed that very little of which calls another as its last action. This
this is about "down to earth" problems. I shows that procedure calls include go t o
have always felt that the transformation statements as a special case; it cannot be
from recursion to iteration is one of the most argued that procedures are conceptually
fundamental concepts of computer science, simpler than go to's, although some people
and that a student should learn it at about have made such a claim.)
the time he is studying data structures. This As a result of applying the above simplifi-
topic is the subject of Chapter 8 in my multi- cation, and adapting it in the obvious way
volume work; but it's only by accident that to the case of a procedure with one parame-
recursion wasn't Chapter 3, since it concep- ter, Example 6 becomes
tually belongs very early in the table of E x a m p l e 6a:
contents. The material just wouldn't fit com-
fortably into any of the earlier volumes; yet procedure treeprint(t); integer t; value ~;
there are many algorithms in Chapters 1-7 L:ift~0
that are recursions in disguise. Therefore it then treeprint(L[t]) ;
print(A[t]) ;
surprises me that the literature on recursion t : = R[t]; g o t o L;
removal is primarily concerned with "baby" fi;
examples like computing factorials or re-
versing lists, instead of with a sturdy toddler But we don't really want that g o t o , so we
like Example 6. might prefer to write the code as follows,
Now let's go to work on the above ex- using Dahl's syntax for iterations as ex-
ample. I assume, of course, that the reader plained above.
knows the standard way of implementing E x a m p l e 6b:
recursion with a stack [20], but I want to
make simplifications beyond this. Rule procedure treeprint(t); integer t; value t;
loop while t ~ 0:
number one for simplifying procedure calls treeprint (L[t]) ;
is: print (A [t]) ;
If the last action of procedure p before it re- t : = R[t];
turns is to call procedure q, simply go t o the repeat;
beginning of procedure q instead.
If our goal is to impress somebody, we
(We must forget for the time being that we might tell them that we thought of Example
don't like go to statements.) It is easy to 6b first, instead of revealing that we got it
confirm the validity of this rule, if, for sim- by straightforward simplification of the
plicity, we assume parameterless procedures. obvious program in Example 6.
For the operation of calling q is to put a re- There is still a recursive call in Example
turn address on the stack, then to execute q, 6b; and this time it's embedded in the pro-
then to resume p at the return address cedure, so it looks as though we have to go
specified, then to resume the caller of p. The to the general stack implementation. How-
ever, the recursive call now occurs in only equally simple way to remove the recursion
one place, so we need not put a return without resorting to something like Example
address on the stack; only the local variable 6c. As I say, it was a shock when I first ran
t needs to be saved on each call. (This is across such an example. Later, Jim Horning
another simplification which occurs fre- confessed to me that he also was guilty, in
quently.) The program now takes the fol- the syntax-table-building program for the
lowing nonrecursive form. XPL system [65, p. 500], because XPL
Example 6c : doesn't allow recursion; see also [56]. Clearly
a now doctrine about sinful go to's is needed ,
p r o c e d u r e treeprint(t); i n t e g e r t; v a l u e t; some sort of "situation ethics".
b e g i n i n t e g e r s t a c k S; S := e m p t y ; The new morality that I propose may
L I : loop w h i l e t ~ 0:
< = t; t := L[t]; go to L1;
perhaps be stated thus: "Certain go t o
L2: t < = S; statements which arise in connection with
print (A[t]) ; well-understood transformations are accept-
t := R[t]; able, provided that the program documenta-
repeat; tion explains what the transformation was."
i f nonempty(S) t h e n g o t o L2 fi;
end. The use of four-letter words like goto can
occasionally be justified even in the best of
Here for simplicity I have extended ALGOL company.
to allow a "stack" data type, where S < = t This situation is very similar to what
means "push t onto S" and t < = S means people have commonly encountered when
"pop the top of S to t, assuming that S is proving a program correct. To demonstrate
nonempty". the validity of a typical program Q, it is
It is easy to see that Example 6c is equiva- usually simplest and best to prove that some
lent to Example 6b. The statement "go t o rather simple but less efficient program P is
L I " initiates the procedure, and control correct and then to prove that P can be
returns to the following statement (labeled transformed into Q by a sequence of valid
L2) when the procedure is finished. Although optimizations. I'm saying that a similar
Example 6c involves go to statements, their thing should be considered standard prac-
purpose is easy to understand, given the tice for all but the simplest software pro-
knowledge that we have produced Example grams: A programmer should create a pro-
6c by a mechanical, completely reliable gram P which is readily understood and
method for removing recursion. Hopkins well-documented, and then he should op-
[44] has given other examples where go t o timize it into a program Q which is very effi-
at a low level supports high-level construc- cient. Program Q may contain go to state-
tions. ments and other low-level features, but the
But if you look at the above program transformation from P to Q should be ac-
again, you'll probably be just as shocked as complished by completely reliable and well-
I was when I first realized what has hap- documented "mechanical" operations.
pened. I had always thought that the use of At this point many readers will say, "But
g o t o statements was a bit sinful, say a he should only write P, and an optimizing
"venial sin"; but there was one kind of g o t o compiler will produce Q." To this I say,
that I certainly had been taught to regard "No, the optimizing compiler would have to
as a mortal sin, perhaps even unforgivable, be so complicated (much more so than any-
namely one which goes into the middle of an thing we have now) that it will in fact be
iteration! Example 6c does precisely that, unreliable." I have another alternative to
and it is perfectly easy to understand Exam- propose, a new class of software which will
ple 6c by comparing it with Example 6b. be far better.
In this particular case we can remove the
go to's without difficulty; but in general Program ManipulationSystems
when a recursive call is embedded in For 15 years or so I have been trying to
~ r "1 ""~'~ a rc~,~,,~ till .~ ~,,,~,~u~u ,., think of how to write a compiler that really
several complex levels of control, there is no produces top quality code. For example,
moved out of their loops; yet we consciously Furthermore, there is a rather simple way
remove them when the running time of the to understand this program, by providing
program is important. suitable "loop invari~nts". At the beginning
Still another type of transformation occurs of the first (outer) loop, suppose the stack
when we go from high-level "abstract" data contents from top tO bottom are t,, . . . , t~
structures to low-level "concrete" ones (see for some n > 0; then the procedure's re-
Hoare's chapter in [17] for numerous ex- maining duty is to accomplish the effect of
amples). In the case of Example 6c, we can
replace the stack by an array and a pointer, treeprint (t) ;
print(A[t,]) ; treeprint(R[t,]) ;
arriving at
E x a m p l e 6d: print(A[tl]) ; treeprint(R[tl]) ; (*)
storing its current value in the program grammer would write for the examples, and
counter, i.e., b y duplicating the program, the other with the object code produced by
letting one part of the text represent t r u e a typical compiler that does only local op-
and the other part false, with jumps be- timizations. The assembly-language pro-
tween the two parts in appropriate places. grammer will keep i, j, v, and up in registers,
Example 7 therefore becomes while a typical compiler will not keep vari-
Example 7a: ables in registers from one statement to
another, except if they happen to be there
i := m;j := n; b y coincidence. Under these assumptions,
v := A[jl; the asymptotic running time for all entire
loop: i f A [ i ] > v
t h e n A[j] := A[i]; g o t o upf fi; Quicksort program based on these routines
upt:i := i+1; will be
w h i l e i < j r e p e a t ; g o t o common; assembled compiled
loop: i f v > A[j]
t h e n A[i] := A[j]; g o t o upt fi; Example 7 202/~N In N 55~6NIn N
upf: j := j--l; Example 7a 1 5 ~ N In N 40N In N
while i < j repeat;
common: A[j] := v;
expressed in memory references to data and
instructions. So Example 7a saves more than
Note that again we have come up with a 25 % of the sorting time.
program which has jumps into the middle of I showed this example to Dijkstra, cau-
iterations, yet we can understand it since we tioning him that the go t o leading into an
know that it came from a previously under- iteration might be a terrible shock. I was
stood program, by way of an understandable extremely pleased to receive his reply [31]:
transformation.
Of course this program is messier than the Your technique of storing the value of up in
the order counter is, of course, absolutely safe.
first, and we must ask again if the gain in I did not faint! I am in no sense "afraid" of a
speed is worth this cost. If we are writing a program constructed that way, but I cannot
sort procedure that will be used many times, consider it beautiful: it is really the same
we will be interested in the speed. The repetition with the same terminating condi-
average running time of Quicksort was tion, that "changes color" as the computation
proceeds.
analyzed b y Hoare in his 1962 paper on the
subject [36], and it turns out that the body He went on to say that he looks forward to
of the loop in Example 7 is performed about the day when machines are so fast t h a t we
2N In N times while the statement up := won't be under pressure to optimize our
false is performed about ~ N In N times, if programs; yet
we are sorting N elements. All other parts of
For the time being I could not agree mare with
the overall sorting program (not shown your closing remarks : if the economies matter,
here) have a running time of order N or less, apply "disciplined optimalization" to a nice
so when N is reasonably large the speed of program, the correctness of which has been
the inner loop governs the speed of the entire established beyond reasonable doubt. Your
sorting process. (Incidentally, a recursive massaging of the program text is then no
longer trickery ad hoe, it is perfectly safe and
version of Quicksort will run just about as sound.
fast, since the recursion overhead is not
part of the inner loop. But in this case the I t is hard for me to express the joy that this
removal of recursion is of great value for letter gave me; it was like having all my
another reason, because it cuts the auxiliary sins forgiven, since I need no longer feel
stack space requirement from order N to guilty about my optimized programs.
order log N.)
Using these facts about inner loop times, Coroutines
we can make a quantitative comparison of Several of the people who read the first draft
Examples 7 and 7a. As with Example 1, it of this paper observed that Example 7a can
seems best to make two comparisons, one perhaps be understood more easily as the
with the assembly code that a decent pro- result of eliminating coroutine linkage instead
though it is slightly cleaner looking than the Each of these programs leads to a Qnick-
method in my book, it is noticeably slower, sort routine that makes about 102~N In N
and we have nothing to fear by using a memory references on the average; the
slightly more complicated method once it former is preferable (except on machines
has been proved correct. Beautiful algo- for which exchanges are clumsy), since it is
rithms are, unfortunately, not always the easier to understand. Thus I learned again
most useful. that I should always keep looking for im-
This is not the end of the Quicksort provements, even when I have a satisfactory
story (although I almost wish it was, since program.
I think the preceding paragraph makes an
important point). After I had shown Ex- Axiomatics of Jumps
ample 8 to my student, Robert Sedgewick, We have now discussed many different
he found a way to modify it, preserving transformations on programs; and there are
the randomness of the sub files, thereby more which could have been mentioned (e.g.,
achieving both elegance and efficiency at the removal of trivial assignments as in [50,
the same'time. Here is his revised program. exercise 1.1-3] or [54, exercise 5.2.1-33]).
E x a m p l e 8a:
This should be enough to establish that a
program-manipulation system will have
i := m-l; j : = n; v : = A[n]; plenty to do.
loop: Some of these transformations introduce
loop: i := i%1; w h i l e A[i] < v repeat;
loop: j : = j - - l ; w h i l e A[j] > v r e p e a t ;
go to statements that cannot be handled
while i < j: very nicely by event:indicators, and in
A[il := : A[jl; general we might expect to find a few pro-
repeat; grams in which go to statements survive.
A[i] : = : A[n]; Is it really a formidable job to understand
(As in the previous example, we assume such programs? Fortunately this is not an
that Aim-1] is defined and < A[n], since insurmountable task, as recent work has
the j pointer might run off the left end.) shown. For many years,: the go to ~tatement
At the beginning of the outer loop the in- has been troublesome in the definition of
variant conditions are now correctness proofs and language semantics;
for example, Hoare and Wirth have pre-
m--l _< i < j < n; sented an axiomatic definition of PASCAL
A[k] < vform-l_< k < i;
A[k] > v for j _< k < n; [41] in which everything but real arithmetic
A[n] = v. and the go to is defined formally. Clint and
Hoare [14] have shown how to extend this
It follows that Example 8a ends with to event-indicator go to's (i.e., those which
A[m]...A[i-1] < v = A[i] _< A [ i + I ] . . . A [ n ] don't lead into iterations or conditionals),
but they stressed that the general case
and m < i < n; hence a valid partition has appears to be fraught with complications.
been achieved. Just recently, however, Hoare has shown
Sedgewick also found a way to improve that there is, in fact, a rather simple way
the inner loop of the algorithm from my to give an axiomatic definition of go t o
book, namely: statements; indeed, he wishes quite frankly
i : = m - - l ; j : = n ; v : = A[n]; that it hadn't been quite so simple. For each
loop: label L in a program, the programmer should
loop: i : = iq-1; w h i l e A[i] < v repeat; state a logical assertion a(L) which is to be
A[j] : = A[i]: true whenever we reach L. Then the axioms
loop: j : = j - - l ; w h i l e h [ j ] > v repeat;
while i < j: {a(L)} go to L {false}
A[il := A[j];
repeat; plus the rules of inference
i f i ~ j then j : = j ~ l ;
A[j] : = v; {~(L)} S{P} t- {a(L)} L:S {P}
are allowed in program proofs, and all and jump on overflow might be
properties of labels and go to's will follow
i f overflow
if the a(L) are selected intelligently. One t h e n overflow : = f a l s e ; g o t o j u m p ;
must, of course, carry out the entire proof else go to no op;
using the same assertion a(L) for each fi;
appearance of the label L, and some choices I still believe that this is the correct way to
of assertions will lead to more powerful write such a program.
results than others. Such situations aren't restricted to in-
Informally, a(L) represents the desired terpreters and simulators, although the
state of affairs at label L; this definition foregoing is a particularly dramatic example.
says essentially that a program is correct if Multiway branching is an important pro-
a(L) holds at L and before all "go to L" gramming technique which is all too often
statements, and that control never "falls replaced by an inefficient sequence of i f
through" a go to statement to the following tests. Peter Naur recently wrote me that he
text. Stating the assertions a(L) is analogous considers the use of tables to control program
to formulating loop invariants. Thus, it is flow as a basic idea of computer science that
not difficult to deal formally with tortuous has been nearly forgotten; but he expects it
program structure if it turns out to be will be ripe for rediscovery any day now. It
necessary; all we need to know is the "mean- is the key to efficiency in all the best; corn-
ing" of each label. priers I have studied.
Some hints of this situation, where one
Reduction of Complication problem reduces to another, have occurred
There is one remaining use of go to for in previous examples of this paper. Thus,
which I have never seen a good replacement, after searching for x and discovering that
and in fact it's a situation where I still it is absent, the "not found" routine can
think go to is the right idea. This situation insert x into the table, thereby reducing the
typically occurs after a program has made a problem to the "found" case. Consider also
multiway branch to a rather large number our decision-table Example 4, and suppose
of different but related cases. A little com- that each period was to be followed by a
putation often suffices to reduce one case to carriage return instead of by an extra space.
another; and when we've reduced one problem Then it would be natural to reduce the
to a simpler one, the most natural thing is post-processing of periods to the return-
for our program to go to the routine which carriage part of the program. In each case, a
solves the simpler problem. go to would be easy to understand.
For example, consider writing an interpre- If we need to find a way to do this without
tive routine (e.g., a microprogrammed saying go to, we could extend Zahn's event
emulator), or a simulator of another com- indicator scheme so that some events are
puter. After decoding the address and fetch- allowed to happen in the t h e n . . , fl part
ing the operand from memory, we do a after we have begun to process other events.
multiway branch based on the operation This accommodates the above-mentioned
code. Let's say the operations include no-op, examples very nicely; but of course it can
add, subtract, jump on overflow, and uncon- be dangerous when misused, since it gives us
ditional jump. Then the subtract routine back all the power of go to. A restriction
might be which allows (statement list)~ to refer to
(event)j only for j > i would be less dan-
operand : = -- operand; g o t o a d d ; gerous.
With such a language feature, we can't
the add routine might be "fall through" a label (i.e., an event indi-
accum := accum -b operand; cator) when the end of the preceding code
tyme : = tyme ...I- 1; is reached; we must explicitly name each
go to no op; event when we go to its routine. ProI~fibiting
"fall through" means forcing a programmer in the same way by different people. Every-
to write "go to common" just before the body knows it is a Good Thing, but as
label "common:" in Example 7a; surpris- McCracken [64] has said, "Few people
ingly, such a change actually makes that would venture a definition. In fact, it is not
program more readable, since it makes the clear that there exists a simple definition as
symmetry plain. Also, the program fragment yet." Only one thing is really clear: Struc-
tured programming is not the process of
s u b t r a c t : operand := - operand; g o t o add;
add: accum : = accum + operand; writing programs and then eliminating their
go to statements. We should be able to
seems to be more readable than if "go to define structured programming without
add" were deleted. It is interesting to referring to go to statements at all; then
ponder why this is so. the fact that go to statements rarely need
to be introduced as we write programs should
follow as a corollary.
3. CONCLUSIONS Indeed, Dijkstra's original article [25]
which gave Structured Programming its
This has been a long discussion, and very name never mentions go to statements at
detailed, but a few points stand out. First, all; he directed attention to the critical
there are several kinds of programming question, "For what program structures can
situations in which go to statements are we give correctness proofs without undue
harmless, even desirable, if we are program- labor, even if the programs get large?" By
ming in ALGOLor PL/I. But secondly, new correctness proofs he explained that he does
types of syntax are being developed that not mean formal derivations from axioms,
provide good substitutes for these harmless he means any sort of proof (formal or in-
go to's, and without encouraging a pro- formal) that is "sufficiently convincing";
grammer to create "logical spaghetti". and a proof really means an understanding.
One thing we haven't spelled out clearly, By program structure he means data struc-
however, is what makes some go to's bad ture as well as contro[strueture.
and others acceptable. The reason is that We understand complex things by sys-
we've really been directing our attentior~ to tematically breaking them into successively
the wrong issue, to the objective question simpler parts and understanding how these
of go to elimination instead of the important parts fit together locally. Thus, we have
subjective question of program structure. different levels of understanding, and each
In the words of John Brown [9], "The act of of these levels corresponds to an abstraction
focusing our mightiest intellectual resources of the detail at the level it is composed from.
on the elusive goal of go to-less programs For example, at one level of abstraction, we
has helped us get our minds off all those deal with an integer without considering
really tough and possibly unresolvable whether it is represented in binary notation
problems and issues with which today's or two's complement, etc., while at deeper
professional programmer would otherwise levels this representation may be important.
have to grapple." By writing this long At more abstract levels the precise value of
article I don't want to add fuel to the con- the integer is not important except as it
troversy about go to elimination, since that relates to other data.
topic has already assumed entirely too much Charles L. Baker mentioned this principle
significance; my goal is to lay that contro- as early as 1957, as part of his 8-page review
versy to rest, and to help direct the discus- [2] of McCracken's first book on program-
sion towards more fruitful channels. ming:
Structured Programming Break the problem into small, self-contained
subroutines, trying at all times to isolate the
The real issue is structured programming, various sections of coding as much as possible
but unfortunately this has become a catch . . . [then] the problem is reduced to many
phrase whose meaning is rarely understood much smaller ones. The truth of this seems
~ ~ ~ ~ .....
292 • Donald E. Knuth
very obvious to experienced coders, yet it is From these remarks it is clear t h a t se-
hard to put across to the newcomer. quential composition, iteration, and condi-
tional statements present syntactic struc-
Abstraction is easily understood in terms tures that the eye can readily assimilate;
of B N F notation. A metalinguistic category but a go t o statement does not. The visual
like (assignment statement) is an abstrac- structure of go t o statements is like that of
tion which is composed of two abstractions flowcharts, except reduced to one dimension
(a (left part list) and an (arithmetic expres- in our source languages. In two dimensions
sion)), each of which is composed of abstrac- it is possible to perceive go t o structure in
tions such as (identifier) or (term), etc. We small examples, but we rapidly lose our
understand the program syntax as a whole ability to understand larger and larger
b y knowing the structural details that relate flowcharts; some intermediate levels of
these abstract parts. The most difficult abstraction are necessary. As an under-
things to understand about a program's graduate, in 1959, I published an octopus
syntax are the identifiers, since their meaning flowchart which I sincerely hope is the most
is passed across several levels of structure. horribly complicated that will ever appear in
If all identifiers of an ALGOL program wer~ print; anyone who believes that flowcharts
changed to random meaningless strings of are the best way to understand a program
symbols, we would have great difficulty is urged to look at this example [49]. (See
seeing what the type of a variable is and also [32, p. 54] for a nice illustration of how
what the program means, but we would go to's make a P L / I program obscure, and
still easily recognize the more local features, see R. Lawrence Clark's hilarious spoof
such as assignment statements, expressions, about linear representation of flowcharts b y
subscripts, etc. (This inability for our eyes means of a " c o m e f r o m statement" [13].)
to associate a type or mode with an identifier I have felt for a long time that a t~dent
has led to what I believe are fundamental for programming consists largely of the
errors of human engineering in the design ability to switch readily from microscopic
of ALGOL 68, but that's another story. M y to macroscopic views of things, i.e., to change
own notation for stacks in Example 6e levels of abstraction fluently. I mentioned
suffers from the same problem; it works in this [55] to Dijkstra, and he replied [29]
these examples chiefly because t is lower with an excellent analysis of the situation:
case and S is upper case.) Larger nested
structures are harder for the eye to see unless I feel somewhat guilty when I have suggested
they are indented, but indentation makes the that the distinction or introduction of "differ-
ent levels of abstraction" allow you to think
structure plain. about only one level at a time, ignoring com-
I t would probably be still better if we pletely the other levels. This is not true. You
changed our source language concept so that are trying to organize your thoughts; that is,
the program wouldn't appear as one long you are seeking to arrange matters in such a
string. John M c C a r t h y says " I find it diffi- way that you can concentrate on some portion,
say with 90% of your conscious thinking, while
cult to believe that whenever I see a tree I the rest is temporarily moved away somewhat
am really seeing a string of symbols." In- towards the background of your mind. But
stead, we should give meaningful names to that is something quite different from "ignor-
the larger constructs in our program that ing completely": you allow yourself tem-
porarily to ignore details, but some overall
correspond to meaningful levels of abstrac- appreciation of what is supposed to be or to
tion, and we should define those levels of come there continues to play a vital role. You
abstraction in one place, and merely use remain alert for little red lamps that suddenly
their names (instead of including the de- start flickering in the corners of your eye.
tailed code) when they are used to build I asked t t o a r e for a short definition of
larger concepts. Procedure names do this, structured programming, and he replied that
but the language could easily be designed it is "the systematic use of abstraction to
so that no action of calling a subroutine is control a mass of detail, and also a means of
implied. documentation which aids program design."
I hope that m y remarks above have made state an overall purpose, for the statement
the abstract concept of abstraction clear; as a whole. !
the second part of Hoare's definition (which We also need well-structured data; i.e.,
was also stressed by Dijkstra in his original as we write the program we should have an
paper [25]) states that a good way to express abstract idea of what each variable means.
the abstract properties of an unwritten piece This idea is also usually describable as an
of program often helps us to write that invariant relation, e.g.,: "m is the number of
program, and to "know" that it is correct items in the table" or "x is the search argu-
as we write it. ment" Or "L[t] is the number of the root
Syntactic structure is just one part of the node of node t's left subtree, or 0 if this
picture, and B N F would be worthless if the subtree is e m p t y " or "the contents of stack
syntactic constructs did not correspond to S are postponed obligations to do such and
semantic abstractions. Similarly, a good such".
program will be composed in such a way Now let's consider the slightly more
that each semantic level of abstraction has a complex case of an event-driven construct.
reasonably simple relation to its constituent This should also correspond to a meaningful
parts. We noticed in our discussion of abstraction, and our examples show what is
Jacopini's theorem that every program can involved: For each event we give an (in-
trivially be expressed in terms of a simple variant) assertion which describes the situa-
iteration which simulates a computer; but tion which must hold when that event
that iteration has to carry the entire be- occurs, and for the loop u n t i l we also give
havior of the program through the loop, so an invariant for the loop. An event statement
it is worthless as a level of abstraction. typically corresponds to an abrupt change
An iteration statement should have a in conditions so t h a t a different assertion
purpose that is reasonably easy to state; from the loop invariant is necessary.
typically, this purpose is to make a certain An error exit can be considered well-
Boolean relation true while maintaining a structured for precisely t h i s \ r e a s o n - - i t
certain invariant condition satisfied by the corresponds to a situation that is~impossible
variables. The Boolean condition is stated according to the local invariant assertions;
in the program, while the invariant should it is easiest to formulate assertions that
be stated in a comment, unless it is easily assume nothing will go ~ o n g , rather than
supplied by the reader. For example, the to make the invariants cover all contin-
invariant in Example 1 is that A[k] ~ x for gencies. When we jump out to an error exit
1 ~ /~ ~ i, and in Example 2 it is the same, we go to another level of abstraction having
plus the additional relation Aim-k 1] = x. different assumptions.
Both of these are so obvious that I didn't As another simple example, consider bi-
bother to mention them; but in Examples nary search in an ordered array using the
6e and 8, I stated the more complicated invariant relation A[i] < x < A[j]:
invariants that arose. In each of those cases
loop while i~l < j;
the program almost wrote itself once the k : = (i+j) + 2;
proper invariant was given. Note that an i f A[k] < x t h e n i :ffi k;
"invariant assertion" actually does vary e l s e i f A [ k ] > x t h e n j :ffi k;
slightly as we execute statements of the]oop, e l s e cannot preserve the invariant fi;
fi;
b u t it comes back to its original form when
repeat;
we repeat the loop.
Thus, an iteration makes a good abstrac- Upon normal exit from this loop, the
tion if we can assign a meaningful invariant conditions i - b l ~ j and A[i] < x < A[3]
describing the local states of affairs as it imply that A[i] < x < A[i-kl], i.e., t h a t x
executes, and if we can describe its purpose is not present. If the program comes to
(e.g., to change one state to another). Simi- "cannot preserve the iinvariant" (because
larly, an i f . - - t h e n -.- else -.- tl state- x = A[k]), it wants to go t o another set of
ment will be a good abstraction if we can assumptions. The event-driven construct
consciously, they won't see the need for go sation, and four computer listings:
to, and the issue will just fade away. On the Frances E. Mien Ralph L. London
other hand, W. W. Peterson told me about Forest Baskett Zohar Manna
his experience teaching P L / I to beginning G. V. Bochmann W. M. McKeeman
programmers: He taught them to use go t o Per Brinch Hansen Harlan D. Mills
R. M. Burstall Peter Naur
only in unusual special cases where i f and Vinton Cerf Kjell Overholt
w h i l e aren't right, but he found [78] t h a t T. E. Cheatham, Jr. James Pe~erson
"A disturbingly large percentage of the John Cocke W. Wesley Peterson
students ran into situations that require Ole-Johan Dahl Mark Rain
go to's, and sure enough, it was often because Peter J. Denning John Reynolds
Edsger Dijkstra Barry K. Rosen
w h i l e didn't work well to their plan, but James Eve E. Satterthwaite, Jr.
almost invariably because their plan was K. Friedenbach D. V. Schorre
poorly thought out." Because of arguments Donald I. Good Jacob T. Schwartz
like this, I'd say we should, indeed, abolish Ralph E. Gorin Richard L. Sites
go t o from the high-level language, at least Leo Guibas Richard Sweet
C. A. R. Hoare Robert D. Tennent
as an experiment in training people to Martin Hopkins Niklaus Wirth
formulate their abstractions more carefully. James J. Homing M. Woodger
This does have a beneficial effect on style, B. M. Leavenworth William A. Wulf
although I would not make such a prohibi- Henry F. Ledgard Charles T. Zaha
tion if the new language features described These people unselfishly devoted hundreds of
above were not available. The question is man-hours to helping me revise the firstdraft; and
whether we should ban it, or educate against I'm sorry that I wasn't able to reconcile all of their
i t ; should we attempt to legislate program interesting points of view. In many places I have
shamelessly used their suggestions without an
morality? In this case I vote for legislation, explicit acknowledgment; this article is virtually
with appropriate legal substitutes in place a joint paper with 30 to 40 co-authors! However,
of the former overwhelming temptations. any mistakes it contains are my own.
A great deal of research must be done if
we're going to have the desired language b y APPENDIX
1984. Control structure is merely one simple
issue, compared to questions of abstract data In order to make some quantitative esti-
structure. I t will be a major problem to keep mates of efficiency, I have counted memory
the total number of language features within references for data and instructions, assum-
tight limits. And we must especially look at ing a multiregister computer without cache
problems of i n p u t / o u t p u t and data for- memory. Thus, each instruction costs one
matting, in order to provide a viable alterna- unit, plus another if it refers to memory;
tive to CoBoL. small constants and base addresses are as-
sumed to be either part of the instruction or
ACKNOWLEDGMENTS present in a register. Here are the code se-
quences developed for the first two examples,
I've benefited from a truly extraordinary amount
of help while preparing this paper. The individuals assuming that a typical assembly-language
named provided me with a total of 144 pages of programmer or a very good optimizing com-
single-spaced comments, plus six hours of conver- piler is at work.
Example 1: r l ~-- 1 1 1
r2 ~ m 2 1
r3 ~ - x 2 1
to test 1 1
loop: A[rl]: r3 2 n-a
t o found i f = 1 n-a
r l ~- r l + l 1 n-1
test: r l : r2 1 n
t o loop i f _4 1 n
notfound: m +-rl 2
A[rl] ~-- r3 2 a
B[rl] ~-- 0 2 a
found: r4 ~-- B[rl] 2 1
r4 ~-- r 4 + l 1 1
B[rl] * - r4 2 1
E x a m p l e 2: r2 ~-- m 2 I
r3 ~--x 2 1
A [ r 2 + l ] ~-- r3 2 1
r l ~--0 1 1
loop: r l ~-- r l + l 1 n
A[rl]: r3 2 n
t o loop i f ~ 1 n
r l : r2 1 1
to found if < 1 1
notfound: m ~-- r l etc. as in Example I.
Example 1: r l ~-- 1 1 1
to test 1 1
iner: r l ¢- i 2 n--1
r l ~-- r 1 + 1 1 n--1
test: rl : m 2 n
t o notfound i f ~ 1 n
i ¢-- r l 2 n-a
r2 ~-- A[rl] 2 nn-a
r2: x 2 n-a
t o found i f -- 1 n-a
t o iner 1 n- 1
notfound: r l ~-- m 2 a
r l ~-- r l T 1 1 a
i 4--rl 2 a
mc-rl 2 a
r l ~--x 2 a
r2¢-i 2 a
A[r2] ~-- r l 2 a
Bit2] ~-- 0 2 a
found: rl ~-- i 2 1
r2 ~-- B[rl] 2 1
r2 ~- r2W1 1 1
B[rl] ~- r2 2 1
[9] BROWN,JOHN R. "In m e m o r i a m . . . " , un- guages, C. Boon [Ed]., ~.nfoteeh State of the
published note, January 1974. Art Report 7, 1972, 217~232.
[10] BRUNO J., AND STIEGLITZ, K. "The expres- [29] DIJKSTRA,E. W. persbnal communication,
sion of algorithms by charts," J. ACM 19, January 3, 1973.
3 (July 1972), 517-525. [30] DIJKSTRA,E. W. personal communication,
[11] BURKHARD,W. A. "Nonrecursive tree tra- November 19, 1973.
versal algorithms," in Proc. 7th Annual [31] DIJKSTRA,E. W. personal communication,
Princeton Conf. on Information Sciences and • January 30, 1974.
Systems, Princeton Univ. Press, Princeton, [32] DONALDSON, JAMES'R. "Structured pro-
N.J., 1973, 403-405. gramming," Datamation 19, 12 (December
[12] CHEATHAM,T. E., JR., ANDWEGBREIT, BEN. 1973), 52-54.
"A laboratory for the study of automating [33] DYLAN, Bos. Blonde on blonde, reeord album
programming," in Proc. A F I P S 1972 Spring produced by Bob John~ston, Columbia Rec-
Joint Computer Conf., Vol. 40, AFIPS Press, ords, New York, March 1966, Columbia C2S
Montvale, N.J., 1972, 11-21. 841.
[13] CLARK,R. LAWRENCE. "A linguistic contri- [34] GILL, STANLEY. "Automatic computing: Its
bution to GOTO-less programming," Data- problems and prizes," Computer J. 8, 3
marion 19, 12 (December 1973), 62-63. (October 1965), 177-189.
[14] GLINT,M., AND HOARE, C. A. R. "Program [35] HENDERSON,P. AND S~OWDON, R. "An ex-
proving: jumps and functions," Acta Infor- periment in structured programming,"
matica 1, 3 (1972), 214-224. B I T 12, 1 (1972),,~8~-5~. ,, _ . ,
[15] COOPER, D. C. "The equivalence of certain [36] HOARE, C. A . R . Quicksort, Computer J.
computations," Computer J. 9, 1 (May 5, 1 (1962), 10-15.
1966), 45-52. [37] HOARE, C. A. R. "An! axiomatic approach
[16] COOPER, D. C. "BShm and Jacopini's re- to computer programming," Comm. ACM
duction of flow charts," Comm. ACM 10, 8 12, 10 (October 1969!, 576-880, 583.
(August 1967), 463, 473. [38] HOARE, C. A. R. 'Proof of a program:
[17] DAHL,O.-J., DIJKSTRA, E. W., AND HOARE, F I N D , " Comm. ACM 14, 1 (January 1971),
C. A. R. Structured programming, Academic 39-45.
Press, London, England, 1972, 220 pp. [39] HOARE, C. A. R. "A note on the for state-
[18] DARLINGTON,J., AND BURSTALL, R. M. "A ment," B I T 12, 3 (1972), 334-341.
system which automatically improves pro- [40] HOARE, C. A. R. "Prospects for a better
grams," in Proc. 8rd Interntl. Conf. on Arti- programming language," in High level lan-
ficial Intelligence, Stanford Univ., Stanford, guages, C. Boon [Ed.], Infotech State of
Calif., 1973, 479-485. the Art Report 7, 1972, 327-343.
[19] DE MARNEFFE, PIERRE-ARNOUL. "Holon [41] HOARE, C. A. R., AND WXRTH,N. "An axio-
programming: A survey," Universite de matic definition of thb programming lan-
Liege, ~ervice Informatique, Liege, Bel- guage PASCAL," Ac~a ln~ormatiea 2, 4
gium, 1973, 135 pp. (1973), 335-355. i
[20] DIJKSTRA, E. W. "Recursive program- [42] HOARE, C. A. R. "Hints for programming
ming," Numerische Mathematik 2, 5 (1960), language design," COmputer Science re-
312-318. port STAN-CS-74-403, Stanford Univ.,
[21] DIJKSTRA,E. W. "Programming considered Stanford, Calif., January 1974, 29 pp.
as a human activity," in Proc. IFIP Con- [43] HOPKINS, M~R~IN E: "Computer aided
gress 1965, North-Holland Publ. Co., Am- software design," in ~oftware engineering
sterdam, The Netherlands, 1965, 213-217. techniques, J. N. Buxton and B. Randell
[22] DIJKSTRA,E. W. "A constructive approach [Eds.] NATO Scientific Affairs Division,
to the problem of program correctness," Brussels, Belgium, 1970, 99-101.
B I T 8, 3 (1968), 174-186. [44] HOPKINS, MARTIN E, "A case for the
[23] DIJKSTRA, E. W. "Go to statement con- GOTO," ProP. ACM Annual Conference
sidered harmful," Comm. ACM l l , 3 (March Boston, Mass., August 1972, 787-790.
1968), 147-148, 538, 541. [45] HULL, T. E. "Would you believe structured
[There are two instances of pages 147-148 FORTRAN?" SIGNUM Newsletter 8, 4
in this volume; the second 147-148 is rele- (October 1973), 13-16. ~
vant here.] [46] INGALLS, DAN. "The execution time pro-
[24] DIJKSTRA,E. W. "Solution of a problem in file as a programming tool," in Compiler
concurrent programming control," Comm. optimization, 2d Courant Computer Sci-
ACM 9, 9 (September 1968), 569. ence Symposium, Randall Rustin [Ed.],
[25] DIJKSTRA, E. W. "Structured program- Prentice-Hall, Englewood Cliffs, N. J.,
ming," in Software engineering techniques, 1972, 107-128.
J. N. Buxton and B. Randell [Eds.] NATO [471 KELLEY,ROBERT A., AND WAVrERS, JOHN
Scientific Affairs Division, Brussels, Bel- R. "APLGOL-2, a structured programming
gium, 1970, 84-88. system for APL," IBM Palo Alto Scientific
[26] DIJKSTRA,E. W. "EWD316: A short intro- Center report 320-3318 i(August 1973), 29 pp.
duction to the art of programming," Tech- [48] KLEENE, S. C. "Representation of events
nical University Eindhoven, The Nether- in nerve nets," in Automata ~tudies, C. E.
lands, August 1971, 97 pp. Shannon and J. McCarthy [Eds.],Princeton
[27] DIJKSTRA, E. W. "The humble program- University Press, Princeton, N.J., 1956, 3-
mer," Comm. ACM 15, 10 (October 1972), 40.
859-866. [49] KNUTH, DONALD E. "RUNCIBLE--Alge-
[28] DIJKSTRA, E. W. "Prospects for a better braie translation on a limited computer,"
programming language," in High level lan- Comm. A C M 2, 11 (November, 1959), 18-21.
[There is a bug in the flowchart. The arc [66] MILLAY, EDnA ST. VINCENT. "Elaine"; el.
labeled "2" from the box labeled "0:" in Bartlett's Familiar Quotations.
the upper left corner should go to the box [67] MILLER, EDWARD F., JR., AND LINDAMOOD,
labeledR~ ffi 8003.] GEORGE E. "Structured programming: top-
[50] KNUTH,DONALDE. Fundamental algorithms, down approach," Datamation 19, 12 (De-
The art of computer programming, Vol. 1, cember 1973)i 55--57.
Addison-Wesley, Reading, Mass. 1968 2d [68] MILLS, H. D~ "Top-down programming in
ed., 1973, 634 pp • large systems," in Debugging techniques in
[51] KNUTH, DONALDE. "An empirical study of large systems, Randall Rustin [Ed.], Pren-
FORTRAN programs,!' Software--Practice tice-Hall, Englewood Cliffs, N. J., 1971, 41-
and Experience 1, 2 (April-June 1971), 105- 55.
133. [69] MILLS, H. D. "Mathematical foundations
[52] KNUTH, DONALDE., AND FLOYD,ROBERT W. for structured programming," report FSC
"Notes on avoiding 'go to' statements," 72-6012, IBM Federal Systems Division,
Information Processing Letters 1, 1 (Febru- Gaithersburg, Md. (February 1972), 62 pp.
ary 1971), 23-31, 177. [70] MILLS, H. D, "How to write correct pro-
[53] KNUTH, DONALD E. "George Forsythe and grams and know i t , " report FSC 73-5008,
the development of Computer Science," IBM Federal Systems Division, Gaithers-
Comm. ACM 15, 8 (August 1972), 721-726. burg, Md. (1973), 26 pp.
[54] KNUTH, DONALD E. Sorting and searching, [71] NASSI, I. R., AND AKKOYUNLU,E. A. "Veri-
The art of computer programming, Vol. 3, fication techniques for a hierarchy of con-
Addison-Wesley, Reading, Mass., 1973, 722 trol structures," Tech. report 26, Dept. of
Computer Science, State Univ. of New
[55] ~NUTH, DONALD E. "A review of 'struc- York, Stony Brook, New York (January
tured programming'," Stanford Computer 1974), 48 pp.
Science Department report STAN-CS-73- [72] NAUR, PETER [Ed.] "Report on the al-
371, Stanford Univ., Stanford, Calif., June gorithmic language ALGOL 60," Comm.
1973, 25 p p - ACM 3, 5 (May 1960), 299-314.
[56] KNUTH, DONALD E., AND SZWARCFITER, [73] NAUR,PETER. "Go to statements and good
JAYME L. "A structured program to gener- Algol style," BIT 3, 3 (1963), 204-208.
ate all topological sorting arrangements," [74] NAUR,PETER. "Program translation viewed
Information Processing Letters 2, 6 (April as a general data processing problem,"
1974) 153-157. Comm. ACM 9, 3 (March 1966), 176--179.
[57] KOSARAJU,S. RAO. "Analysis of structured [75] NAUR, PETER. "An experiment on program
rograms," Proe. Fifth Annual ACM Syrup. development," BIT 12, 3 (1972), 347-365.
heory of Computing, (May 1973), 240-252; {76] PAGER, D. "Some notes on speeding up
also in J. Computer and System Sciences, 9, certain loops by software, firmware, and
3 (December 1974). hard w are means, '~ in" Computers and auto-
[58] LANDIN, P. J. "A correspondence between mata, Jerome Fox lEd.f, John Wiley & Sons,
ALGOL 60 and Church's lambda-notation: 1yew x o r k 1972, 207-213; also in IEEE
part I , " Comm. ACM 8, 2 (February 1965), Trans. Computers, C-21, 1 (January 1972),
89-101. 97-100.
[59] LANDIN, P. J. "The next 700 programming
languages," Comm. ACM 9, 3 (March 1966), [77] PETERSON, W. W.; KASAMI, T.; AND TOK-
157-166. UEA, N. "On the capabilities of w h i l e , re-
[60] LEAVENWORTH, B. M. "Programming p e a t , and exit statements," Comm. ACM
with(out) the GOTO," Proc. ACM Annual 16, 8 (August 1973), 503-512.
Conference, Boston, Mass., August 1972, 782- [78] PETERSON,W. WESLEY. personal communi-
786. cation, April 2, 1974.
[61] MANNA, ZOHAR, AND WALDINGER, RICHARD [79] RAIN, MARK AND HOLAOER, PER. "The
J. "Towards automatic program synthesis," present most recent final word about labels
in Symposium on Semantics of Algorithmic in MARY," Machine Oriented Languages Bul-
Languages, Lecture Notes in Mathematics letin 1, Trondheim, Norway (October 1972),
188, E. Engeler [Ed.], Springer-Verlag, New 18-26.
York, 1971, 270-310. [80] REID, CONSTANCE.Hilbert, Springer-Verlag,
[62] McCARTHY, JOHN. "Reeursive functions New York, 1970, 290 pp.
of symbolic expressions and their compu- [81] REYNOLDS,JOHN. "Fundamentals of struc-
tation by machine, part I , " Comm. ACM 3, tured programming," Systems and Info.
4 (April 1960), 184-195. Set. 555 course notes, Syracuse Univ., Syra-
[63] MCCARTHY,JOHN. "Towards a mathemati- cuse, N.Y., Spring 1973.
cal science of computation," in Proc. IFIP [82] SATTERTHWAITE, E. H. "Debugging tools
Congress 1962, Munich, Germany, North- for high level languages," Software--Practice
Holland Publ. Co., Amsterdam, The Nether- and Experience 2, 3 (July-September 1972),
lands, 1963, 21-28. 197-217.
[64] McCRACKEN, DANIEL D. "Revolution in [83] SCHNECK, P. B., AND ANGEL, ELLINOR. " A
• rogranmaing," Datamation 19, 12 (Decem-
er 1973), 50-52.
FORTRAN to FORTRAN optimizing com-
piler," Computer J. 16, 4 (1973), 322-330.
[65] McKEEMAN, W. M.; HORNING, J. J.; AND [84] SCHORRE, D. V. "META-II--a syntax-di-
WORTMAN, D. B. A compiler generator, rected compiler writing language," Proc.
Prentice-Hall, Englewood Cliffs, N. J., ACM National Conference, Philadelphia,
1970, 527 pp. Pa., 1964, paper D1.3.