
Thinking about Algol 68
In memory of J. Kevin Douglas, a good friend and fellow fan of Algol 68
I took my first computer science course in my second year at the University of British Columbia in Vancouver, Canada. The course was a full year, starting in September 1974, and we programmed in Waterloo FORTRAN IV, which if memory serves was called Watfor or maybe Watfiv at the time. We also had a brief session with IBM 360 / 370 Assembler language. Both languages were available to us in the form of batch timeshare services where we wrote our programs on IBM 029 key punches and submitted the card decks to be run, generating printouts which were almost entirely compilation or execution failures interspersed with the occasional output of a program that generated the hoped-for results.
In sum, things were pretty basic “back in the day”. Nevertheless I kept at it and in my next and subsequent years as an undergrad had access to interactive terminals and many other programming languages, including PL/1, Pascal, BCPL, LISP, Algol W, APL…
… And Algol 68.
My friend and fellow student Kevin Douglas, who was much more of a computer scientist than I will ever be, introduced me to Algol 68. There were graduate students at UBC working on Algol 68 implementations. Professor J.E.L. Peck, an Algol 68 luminary and member of the committee in charge of designing the language, was head of the department. While my interests in computer science tended more toward numerical analysis, what I perceived as the sheer expressiveness of Algol 68 was a powerful distraction.
And the language itself – said to be somewhere between extremely difficult and impossible to compile due to its innovative two level grammar, and yet at the same time astonishingly elegant for its orthogonality and resulting expressive nature – who could not fall under the charms of that? Finally, let’s all face it – if the main goal of a new computer language is to make it easy to compile into machine code, then we’d all still be writing in assembly language. Or maybe something like PL/360.
As it turns out, Algol 68 accomplished two main things beyond all the design and implementation efforts:
- It influenced, to some degree at least, the design of many subsequent languages and utilities, including C and the Bourne shell;
- It created a legion of opposing parties, who not only sat on the sidelines heckling, but in some cases, built really useful things to show that there were other ways to proceed, including the Pascal and Ada programming languages.
Fast forward to 2025, and Algol 68 seems to many to be a historical oddity; a programming language that had as much negative influence as positive. Most people that I have run into who have even heard of Algol 68 “know” that it is a complicated language full of weird theoretical ideas that have not aged well, and in the end neither of great utility nor of great interest.
In my opinion and experience, Algol 68 is largely a victim of mostly misinformed – or uninformed – gossip, and the wisdom and efforts of its designers and implementers are worthy of more reasonable consideration. Therefore, I hope to show that this language remains relevant, interesting and even useful going on 60 years later. I hope to dispel some of the “received ideas” around the language. And I hope to achieve this by demonstrating some simple and useful code examples that show many aspects of the language worth learning and using.
What makes my quest much easier and more relevant are two fine current, maintained implementations of Algol 68 that are ready for experimentation, and in many cases, daily use. These are:
- Algol 68 Genie, a compiler – interpreter developed and maintained by Marcel van der Veer;
- GNU Algol 68, a recent and ongoing project to develop a production quality compiler based on the GNU Compiler Collection tools, being developed by Jose Marchesi.
Of even greater importance is that both of these excellent Algol 68 implementations are open source.
A first example
Let’s take a look at our first simple Algol 68 program, which demonstrates a few important Algol 68 details.
1 BEGIN
2 first random(42);
3 REAL sum of randoms := 0.0;
4 WHILE sum of randoms < 10.0 DO
5 REAL r := next random;
6 sum of randoms +:= r;
7 print(("random number = ",r,"; sum = ",sum of randoms,new line))
8 OD
9 END
Line 1 – BEGIN, line 9 – END and all the stuff between form an Algol 68 closed clause. BEGIN and END serve a similar purpose to { and } in C, Java and similar languages, and to begin and end in Pascal.
Clauses are an important concept in the definition of Algol 68. Page 53 of the Revised Report states:
(Clauses provide
- a hierarchical structure for programs,
- the introduction of new ranges of definitions,
- serial or collateral composition, parallelism, choices and loops.)
In our program, the stuff between BEGIN and END above is an example of a serial clause, that is, a collection of expressions that are evaluated serially (one after another). BEGIN and END are written in upper case to indicate that they are pre-defined symbols known to the compiler.
Line 2 calls the procedure “first random” with the argument “42”. Here we see a space between “first” and “random”; this could also be written as “firstrandom”, “fi r stran dom” or various other combinations since spaces don’t matter within the names of variables, procedures and so forth. “First random” is a predefined procedure that initializes a random number generator based on its argument.
Line 3 declares a real number variable called “sum of randoms” and initializes it to 0.0, a real constant. Note that the assignment operator in Algol 68 is “:=”. Not seen here is the equality comparison operator, which is “=”. Contrast this to assignment in C which is “=” and equality comparison which is “==”.
We will talk more about variable declarations, assignment and equality operators soon.
Note also that lines 2 and 3 are separated by a semicolon, what Algol 68 calls a go on symbol. Algol 68 thinks of semicolons as separators, not terminators (as in C).
Line 4 is the start of a loop clause, ending on line 8, which encloses a collection of expressions to be evaluated repetitively and serially. In this case, the looping continues until the value of “sum of randoms” is greater than or equal to 10.0. Note that the tag OD ends the serial clause opened by the tag DO. Compare this to a similar construct in C which would be:
while (sum_of_randoms < 10.0) { … }
Line 5 declares the real number variable “r” which is local to the loop and assigns to it the value of the “next random” procedure, being the next random number in the sequence.
Line 6 increments the value of “sum of randoms” by the value of “r”. The use of the “+:=” or “plus and becomes” operator is equivalent to:
sum of randoms := sum of randoms + r
Line 7 prints the values of “r” and “sum of randoms” with preceding string labels and a trailing new line character inserted into the output stream by a call to the “new line” predefined procedure.
Worth mentioning here are the double parentheses following “print” and ending the expression. The outermost pair “()” enclose the argument to “print”, while the innermost pair surround a collateral clause, in this case a list of expressions separated by commas. The “print” procedure only accepts one argument, but that argument can be an array, or row; the collateral clause, enclosed by parentheses, is in this case a row display creating a list (Algol 68 terminology for what we might call a list).
In summary, the row display
("random number = ",r,"; sum = ",sum of randoms,new line)
Is similar to a Java initializer like
{ “random number = “, r, “; sum = “, sum_of_randoms, new_line}
The astute reader may well be wondering about an array of expressions of clearly different types like string, real and whatever new_line is. We will eventually discuss that!
For now, I can compile and run this program using Algol 68 Genie in a Linux terminal window as follows:
$ a68g a1.a68
random number = +2.61736743850634e -1; sum = +2.61736743850634e -1
random number = +2.44074219372123e -2; sum = +2.86144165787846e -1
random number = +4.19119445839897e -1; sum = +7.05263611627743e -1
random number = +4.84060694929212e -1; sum = +1.18932430655695e +0
random number = +6.92153602372855e -1; sum = +1.88147790892981e +0
random number = +4.53971547773108e -1; sum = +2.33544945670292e +0
random number = +6.70357855502516e -1; sum = +3.00580731220543e +0
random number = +8.19231704808772e -1; sum = +3.82503901701421e +0
random number = +8.88931809924543e -1; sum = +4.71397082693875e +0
random number = +4.38520186813548e -1; sum = +5.15249101375230e +0
random number = +8.07107185712084e -1; sum = +5.95959819946438e +0
random number = +9.24482085043564e -1; sum = +6.88408028450795e +0
random number = +7.35386690590531e -1; sum = +7.61946697509848e +0
random number = +3.30123137915507e -1; sum = +7.94959011301398e +0
random number = +4.65522854821756e -1; sum = +8.41511296783574e +0
random number = +9.83509750338271e -1; sum = +9.39862271817401e +0
random number = +6.23938688309863e -1; sum = +1.00225614064839e +1
$
That’s it for now. In the next article, we’ll dig into a few of the less obvious but still important details that make this all work. Then we can move on to see some more cool things that we can do in Algol 68.