Algol 68 style guide
last modified November 14, 2026
Algol 68 gives the programmer more freedom than most languages of its age: the layout is free, an identifier may contain spaces, the same program can be written in more than one stropping convention, and the priority table can be extended by the program itself. Freedom of that kind needs a convention, and the convention used in this series is the one below.
The rules are short: res stropping, lower-case names, two spaces of indentation, parentheses around mixed boolean operators, a mode for every structure that is used more than once, and no extensions in code that should run on another implementation.
Use res stropping
Write keywords and mode names in upper case and identifiers in lower case. This is res stropping, the default of the language and of the interpreter, and it needs no command-line option. The case is the only marker, so the convention must be followed exactly: a keyword written in lower case is an identifier, and the program stops with an undeclared tag.
BEGIN
INT total := 0;
FOR i TO 3 DO
total +:= i
OD;
print(("total ", whole(total, 0), newline))
END
Quote stropping is available with --quote-stropping, and the
stropping article uses it where the quoted
form is the point. It is not used in this series, because it adds two
characters to every keyword and makes predeclared names easy to quote by
mistake. Point stropping and bold stropping are not available in version
2.8.4.
$ a68g style.a68 total 6
Name things in lower case
An identifier may contain letters, digits, underscores, and spaces, and the
spaces are ignored. my count and mycount are the
same name, which means that a stray space cannot change a meaning but can
make a name hard to search for. Use lower case and write the name the same
way everywhere.
BEGIN INT item count = 5; INT sum3 = itemcount + 10; print((whole(sum3, 0), newline)) END
The declaration uses a space and the use does not, yet both refer to one
variable. Names in this series are single words, or a verb followed by a
noun, such as read line written as readline. A
digit at the end of a name is allowed; a digit in the middle of an operator
tag is not, so operator names stay alphabetic.
$ a68g names.a68 15
Lay out one unit per line
The compiler ignores layout, so the only purpose of indentation is to show
the structure to a reader. Put one declaration or statement on a line, indent
the body of a clause by two spaces, and place THEN,
ELSE, FI, DO, and OD on
lines of their own when the body is longer than one line.
PROC average = ([]INT values) REAL:
(
INT sum := 0;
FOR i FROM LWB values TO UPB values DO
sum +:= values[i]
OD;
sum / (UPB values - LWB values + 1)
);
BEGIN
[]INT data = (4, 8, 15, 16, 23, 42);
print((fixed(average(data), 0, 1), newline))
END
The body of the procedure is enclosed in parentheses, one at each end, and
the loop body is indented once inside them. The final expression is the
result, so it needs no RETURN. The
--pretty-print option of the interpreter produces this layout
from a crowded file, as the listings article
shows, and is a reasonable first pass before the layout is adjusted by hand.
$ a68g average.a68 18.0
Parenthesise mixed boolean operators
AND has priority 3 and OR has priority 2, so
TRUE OR FALSE AND FALSE is true: the conjunction is evaluated
first. The reading is correct but not obvious, and a reader who expects the
operators to be applied from left to right will misread the condition.
BEGIN print((TRUE OR FALSE AND FALSE, newline)); print((TRUE OR (FALSE AND FALSE), newline)); print(((TRUE OR FALSE) AND FALSE, newline)) END
The first two lines print T and the third prints
F, which is the whole argument for the parentheses: they make
the difference visible in the source. The same advice applies to a mixture of
comparisons, arithmetic, and selection, where the priority table is easy to
forget.
$ a68g logic.a68 T T F
Introduce a mode for a repeated structure
A structure that appears in more than one declaration deserves a name.
MODE POINT = STRUCT (REAL x, REAL y) turns a pair of reals into
a value that a procedure can take and return, and the field names replace the
positional order at every call site.
MODE POINT = STRUCT (REAL x, REAL y); PROC distance = (POINT a, POINT b) REAL: sqrt((x OF a - x OF b) ** 2 + (y OF a - y OF b) ** 2); BEGIN POINT p = (0, 0); POINT q = (3, 4); print((fixed(distance(p, q), 0, 2), newline)) END
The procedure takes the structure by value, because it only reads the
fields; a procedure that changes a point would take REF POINT.
The mode is declared once and used in both parameters and in the two
declarations, so a change from REAL to LONG REAL is
one edit rather than four.
$ a68g point.a68 5.00
Comment the reason, not the syntax
A comment written between # marks runs to the next
#, and a comment written between the words COMMENT
runs to the next COMMENT. Use the short form for a note on one
line and the long form to disable a block of code, which is the one place
where a comment that repeats the code is useful.
# The rate is a percentage, so 5 means five percent. # PROC interest = (REAL amount, REAL rate) REAL: amount * rate / 100; BEGIN # 200 at 5 percent for one year # print((fixed(interest(200, 5), 0, 2), newline)) END
Both comments state something that the code does not: the unit of the rate
and the arguments of the call. A comment such as # add one to
count # above count +:= 1 would add nothing, and the
layout already shows which clause the note belongs to.
$ a68g interest.a68 10.00
Avoid extensions in portable code
Algol 68 Genie adds operators that the Revised Report does not define. The
most useful are ANDF and ORF, which stop at the
first operand that decides the result, while AND and
OR evaluate both. A program that may be moved to another
implementation should avoid them, and the interpreter can warn about them.
BEGIN
INT a := 0;
IF a /= 0 ANDF 10 OVER a > 1 THEN
print(("ok", newline))
FI
END
The option --portcheck prints a warning for each extension and
still runs the program, while --strict rejects the extension as
a syntax error. The portable form of the test cannot short-circuit, so it
nests two conditions: IF a /= 0 THEN IF 10 OVER a > 1 THEN ...
FI FI. The division is then guarded by the first condition rather
than by the second operand of a conjunction.
$ a68g --portcheck portable.a68
3 IF a /= 0 ANDF 10 OVER a > 1 THEN
1
a68g: warning: 1: and-function is an extension.
$ a68g --strict portable.a68
3 IF a /= 0 ANDF 10 OVER a > 1 THEN
1
a68g: syntax error: 1: tag "ANDF" has not been declared properly.
$ echo $?
1
A checklist
Before a file is finished, check the names, the layout, and the portability in
that order. Names should be lower case and spelled the same way everywhere;
the layout should show the clause structure without counting characters; a
condition that mixes boolean operators should have parentheses; a structure
that appears twice should have a mode; and a program that uses
ANDF, ORF, or another extension should be run once
with --portcheck.
The interpreter helps with two of these checks. --pretty-print
rewrites the layout, and --strict rejects the extensions that
--portcheck only warns about. The
program structure article covers
the block and the prelude, and operators
has the priority table that the parentheses are meant to override.
Source
Revised Report on the Algorithmic Language Algol 68
In this article we chose res stropping, named values in lower case, laid out one unit per line, parenthesised mixed boolean operators, introduced a mode for a repeated structure, wrote comments that explain the reason, and checked a program for extensions.
Author
List all Algol 68 tutorials.