Algol 68 loops
last modified November 13, 2026
A loop repeats a unit until a condition says otherwise. Algol 68 builds every
loop from the same clause, which starts with FOR, lists the
values to walk through, tests an optional condition, and closes with
OD. This article describes the parts of that clause and the two
ways to leave a loop early, which are a false condition or a jump to a label.
Counting with FOR
The shortest loop form is FOR followed by a control variable and
TO an upper bound. It repeats the unit between DO
and OD, and the control variable takes each integer from 1 to
the bound. The variable is declared by the loop itself, so the program does
not declare it beforehand.
BEGIN
FOR i TO 5 DO
print((whole(i, 0), " "))
OD;
print((newline))
END
The five passes print the numbers 1 to 5, each followed by a space. The
control variable exists only inside the loop: after OD it is no
longer declared, so a program that needs the last value must copy it into a
variable of its own. The control variable is also read only, and assigning to
it inside the body is rejected.
$ a68g count.a68 1 2 3 4 5
FROM and BY
The full form of the loop adds a starting value and a step. The parts are
written in the order FROM, BY, TO;
FROM and BY may be left out, and a
WHILE condition may stand in place of TO. A
negative step counts downwards, so the loop stops when the value passes the
upper bound from the other side.
BEGIN
FOR i FROM 0 BY 5 TO 20 DO
print((whole(i, 0), " "))
OD;
print((newline));
FOR i FROM 10 BY -2 TO 1 DO
print((whole(i, 0), " "))
OD;
print((newline))
END
The first loop starts at 0 and adds 5 on every pass, which gives 0, 5, 10,
15, and 20. The second starts at 10 and subtracts 2, so it prints 10, 8, 6,
4, and 2; the value 0 is never reached because it lies beyond the bound of 1.
Writing the parts in a different order, as in FROM 0 TO 20 BY 5,
is a syntax error.
$ a68g step.a68 0 5 10 15 20 10 8 6 4 2
Counting down with DOWNTO
DOWNTO is a keyword of its own rather than a combination of
DOWN and TO. It sets the step to -1, which makes the
loop a shorthand for counting from the first value down to the second one.
BEGIN
FOR i FROM 5 DOWNTO 1 DO
print((whole(i, 0), " "))
OD;
print((newline));
FOR i TO 3 DO
print(("*"))
OD;
print((newline))
END
The first loop prints 5, 4, 3, 2, 1. The second one shows that a loop may
also run for its effect alone: it prints three stars. When the first value is
already past the second one, as in FOR i FROM 5 TO 1, the loop
runs zero times instead of counting backwards.
$ a68g downto.a68 5 4 3 2 1 ***
WHILE loops
A WHILE loop has no range at all. It tests a boolean condition
before every pass and stops as soon as the condition is false, so the body
must change something that the condition depends on.
BEGIN
INT n := 1;
WHILE n < 100 DO
print((whole(n, 0), " "));
n *:= 2
OD;
print((newline))
END
The variable is doubled on each pass, so the loop prints the powers of two below 100. The last value printed is 64, because the next one, 128, fails the test before the body runs. The condition is tested first, which means that a loop whose condition is false from the start never runs at all.
$ a68g while.a68 1 2 4 8 16 32 64
Combining FOR and WHILE
A loop may carry both a range and a condition. The range gives the largest number of passes and the condition stops the loop earlier, which is useful when a total reaches a limit.
BEGIN
INT total := 0;
FOR i TO 10 WHILE total < 10 DO
total +:= i
OD;
print((whole(total, 0), newline))
END
The body adds 1, 2, 3, and 4, and the total becomes 10. The condition is then
false, so the loop stops at the fifth pass even though the range would allow
ten. The condition is written after TO and before
DO, and both parts are tested before each pass.
$ a68g forwhile.a68 10
Unconditional loops
When the loop has neither a range nor a condition, it repeats forever. Such a
loop is written with DO and OD alone, and the
program leaves it with a jump to a label placed after the clause.
BEGIN
INT n := 0;
DO
n +:= 1;
print((whole(n, 0), " "));
IF n = 3 THEN GO TO finished FI
OD;
finished:
print((newline))
END
The label finished: names the unit that follows it, and
GO TO finished transfers control there. The jump leaves the loop
without asking the condition, which is the only way out of a loop that has
none. A label is written as an identifier followed by a colon and may be
placed in front of any unit.
$ a68g unconditional.a68 1 2 3
Labels and nested loops
A jump can leave several loops at once, which a condition cannot do. The example stops the inner loop as soon as the column number passes the row number, so each row prints one value more than the previous one.
BEGIN
FOR i TO 3 DO
FOR j TO 3 DO
IF j > i THEN GO TO next row FI;
print((whole(i * j, 0), " "))
OD;
next row:
print((newline))
OD
END
The inner loop would print three values for every row, but the jump to
next row skips the rest of the row instead. The label sits inside
the outer loop, so the jump only leaves the inner one and the outer loop
continues. Labels are visible throughout the clause that declares them, which
is why the inner clause can jump to a label written after it.
$ a68g nested.a68 1 2 4 3 6 9
Next steps
The conditionals article explains the
IF clauses that appear inside these loops, and the
procedures article shows how to move a loop
body into a procedure of its own. The rows
article uses loops to walk through the elements of a row, and
operators explains the compound assignments
such as +:= and *:=.
Source
Revised Report on the Algorithmic Language Algol 68
In this article we have counted with FOR and TO,
set a start and a step with FROM and BY, counted
downwards with DOWNTO, repeated units with WHILE,
combined a range with a condition, written an unconditional loop, and left
loops with labels and GO TO. The
procedures article continues with the units
that the loops call.
Author
List all Algol 68 tutorials.