ZetCode

Algol 68 procedures

last modified November 13, 2026

A procedure packages a unit under a name, gives it parameters, and optionally returns a value. Algol 68 declares it with PROC, writes the modes of the parameters in parentheses, writes the mode of the result after the colon, and then gives the body. This article describes those declarations, reference parameters, recursion, and the fact that a procedure is itself a value that can be stored and passed.

Declaring a procedure

The simplest procedure returns nothing, so its result mode is VOID. The body follows a colon and may be any unit, including a single call of print. Calling the procedure writes its name, and because there are no parameters, no parentheses follow.

simple.a68
PROC greet = VOID: print(("Hello from a procedure", newline));

BEGIN
  greet;
  greet
END

The declaration ends with a semicolon, like any other declaration, and the body is the call of print after the colon. Each of the two calls prints the line, so the output appears twice. A procedure that returns a value behaves the same way, except that the value may be used in a formula.

$ a68g simple.a68
Hello from a procedure
Hello from a procedure

Parameters and a result

Parameters are declared as a comma-separated list of modes and names, and the result mode is written between the closing parenthesis and the colon. The body must produce a value of that mode.

params.a68
PROC area = (REAL width, REAL height) REAL: width * height;

BEGIN
  print((fixed(area(3.0, 4.5), 0, 2), newline));
  print((fixed(area(2.0, 2.0), 0, 2), newline))
END

The first call passes 3.0 and 4.5 and returns 13.5, the second returns 4.0. The parameters are values, so the procedure receives copies and cannot change the caller's variables through them. The arguments must have the declared modes; an integer argument would be widened to REAL automatically, but nothing else would be converted.

$ a68g params.a68
13.50
4.00

A body of several statements

When the body needs declarations or several statements, it is written as a parenthesised serial clause. The value of the last unit in that clause is the value of the procedure, so a conditional clause at the end chooses the result.

body.a68
PROC classify = (INT n) STRING:
  ( IF n < 0 THEN "negative"
    ELIF n = 0 THEN "zero"
    ELSE "positive"
    FI );

BEGIN
  print((classify(-5), " ", classify(0), " ", classify(7), newline))
END

The parentheses around the body form a serial clause with a single unit, and that unit is the conditional clause. Because every branch yields a string, the clause has mode STRING and the declaration is accepted. The calls print the three classifications in one line.

$ a68g body.a68
negative zero positive

Reference parameters

A parameter declared with REF designates a variable rather than copying its value, so the procedure can store into the caller's variable. The argument must be a name of the required mode, not an arbitrary formula.

swap.a68
PROC swap = (REF INT a, REF INT b) VOID:
  (INT t := a; a := b; b := t);

BEGIN
  INT x := 1, y := 2;
  swap(x, y);
  print((whole(x, 0), " ", whole(y, 0), newline))
END

The body saves the first value in a local variable and then exchanges the two cells. The call passes the names x and y, so the assignments reach the caller's variables and the output is 2 1. Passing a formula such as swap(x, 1) would be rejected, because a formula does not designate storage.

$ a68g swap.a68
2 1

Recursion

A procedure may call itself, and the declaration is visible inside its own body. Recursion is natural in Algol 68 because a procedure is an ordinary declaration, so the name is in scope from the start of the body.

fact.a68
PROC factorial = (INT n) INT:
  IF n <= 1 THEN 1 ELSE n * factorial(n - 1) FI;

BEGIN
  FOR i TO 6 DO
    print((whole(factorial(i), 0), " "))
  OD;
  print((newline))
END

The base case returns 1 for 0 and 1, and every other call multiplies its argument by the factorial of the next smaller number. The loop prints the first six factorials. The recursive call appears inside a formula, which is allowed because the procedure yields an integer like any other operand.

$ a68g fact.a68
1 2 6 24 120 720

Procedures as values

A procedure has a mode of its own, written with PROC, the parameter modes, and the result mode. A variable of that mode holds a procedure, and assignment changes which one the name refers to.

procvar.a68
PROC add = (INT a, INT b) INT: a + b;
PROC mul = (INT a, INT b) INT: a * b;

BEGIN
  PROC (INT, INT) INT op := add;
  print((whole(op(3, 4), 0), newline));
  op := mul;
  print((whole(op(3, 4), 0), newline))
END

The variable op starts as add and later becomes mul, so the same call text produces 7 and then 12. The mode PROC (INT, INT) INT is part of the declaration, which means that only procedures with two integer parameters and an integer result may be assigned to it.

$ a68g procvar.a68
7
12

Procedures as arguments

Because a procedure is a value, it can be passed to another procedure. The parameter mode names the shape of the procedure that the argument must have, and the receiving procedure calls it like any other name.

higher.a68
PROC apply = (PROC (INT) INT f, INT x) INT: f(x);
PROC square = (INT n) INT: n * n;
PROC cube = (INT n) INT: n * n * n;

BEGIN
  print((whole(apply(square, 5), 0), " ", whole(apply(cube, 5), 0), newline))
END

apply takes a procedure of mode PROC (INT) INT and an integer, and calls the procedure with that integer. The two calls give 25 and 125. This is how a sorting routine can receive a comparison function, which keeps the order of the elements separate from the algorithm that rearranges them.

$ a68g higher.a68
25 125

Partial parametrisation

A call may leave some arguments out, writing an empty pair of parentheses in their place. The result is a new procedure with the remaining parameters, which Algol 68 calls partial parametrisation.

partial.a68
PROC add = (INT a, INT b) INT: a + b;

BEGIN
  PROC (INT) INT inc = add(1,);
  print((whole(inc(41), 0), newline))
END

The declaration add(1,) supplies the first argument and leaves the second one open, so inc has mode PROC (INT) INT. Calling inc(41) completes the call and returns 42. The omitted argument is marked by the comma alone, which is why the empty parentheses are written after it.

$ a68g partial.a68
42

Scope in nested declarations

A procedure declared inside a clause sees the names that were declared before it. The binding is lexical: the body refers to the declaration that surrounds it, not to a variable of the same name in a clause that happens to be active at the time of the call.

nested.a68
BEGIN
  INT base = 10;
  PROC offset = (INT n) INT: n + base;
  print((whole(offset(5), 0), newline));
  BEGIN
    INT base = 100;
    print((whole(offset(5), 0), newline))
  END
END

Both calls print 15, because offset was declared next to base = 10 and keeps referring to that variable. The inner base is a different variable with a shorter scope, and it does not affect the procedure. This is the same rule that gives a procedure access to the names of the clause in which it is written.

$ a68g nested.a68
15
15

Next steps

The loops article shows the clauses that these procedures usually contain, and the conditionals article explains the branches used in the bodies above. The modes article describes the parameter and result modes, and variables and references explains REF in more detail.

Source

Revised Report on the Algorithmic Language Algol 68

The Algol 68 Genie project

In this article we have declared procedures with and without results, passed values and references, written a recursive procedure, stored procedures in variables, passed them as arguments, left arguments open with partial parametrisation, and seen the lexical scope of a nested declaration. The strings article continues with the operations that procedures perform on text.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Algol 68 tutorials.