Beginner

Operators in ALGOL 68

Explore arithmetic, comparison, logical, and assignment operators in ALGOL 68, including its famous user-defined operator facility

Introduction

Operators in ALGOL 68 are more than syntactic conveniences — they are first-class citizens of the language. ALGOL 68 was one of the earliest languages to support user-defined operators with custom precedence, an idea that later influenced C++, Haskell, and many modern languages. The standard prelude itself defines most operators in ALGOL 68 terms, meaning the line between built-in and user-written operators is delightfully thin.

Because ALGOL 68 is a strongly, statically typed imperative language with structural type equivalence, every operator carries a precise mode signature. The compiler chooses which + to apply based on the modes of its operands, much like an early form of overloading. This tutorial walks through the core operator families you will reach for every day: arithmetic, comparison, logical, and assignment — then closes with a peek at how to invent your own operator.

You will learn how OVER and MOD differ from /, why ALGOL 68 spells AND and OR as words (with optional symbolic synonyms), how the assignment operator := returns a reference, and how to use the +:= and -:= shorthand assignments.

Arithmetic and Comparison Operators

ALGOL 68 distinguishes integer division from real division: / always yields a REAL result, while OVER (synonym %) performs truncating integer division and MOD (synonym %*) returns the integer remainder. The power operator is ** (synonym UP). Comparison operators come in both word and symbolic forms: = / /=, < / >, LE / GE.

Create a file named operators.a68:

BEGIN
  INT a = 17, b = 5;

  print(("a = ", a, ", b = ", b, new line));
  print(("a + b   = ", a + b, new line));
  print(("a - b   = ", a - b, new line));
  print(("a * b   = ", a * b, new line));
  print(("a / b   = ", a / b, new line));
  print(("a OVER b = ", a OVER b, new line));
  print(("a MOD b  = ", a MOD b, new line));
  print(("a ** 2   = ", a ** 2, new line));

  print((new line, "Comparisons:", new line));
  print(("a = b   is ", a = b, new line));
  print(("a /= b  is ", a /= b, new line));
  print(("a > b   is ", a > b, new line));
  print(("a <= b  is ", a <= b, new line))
END

Two things are worth noticing. First, / returns a REAL (printed in scientific notation like +3.40000000000000e +0) — even though both operands are INT, the result mode of / is REAL. Second, ALGOL 68 prints booleans as T or F, reflecting its compact I/O conventions.

Logical Operators and Short-Circuit Evaluation

ALGOL 68 spells boolean operators as AND (synonym &), OR (synonym \/ in stropped notation), and NOT (synonym ~). Like most modern languages, AND and OR short-circuit: the right operand is not evaluated if the result is already determined by the left.

Create a file named logical.a68:

BEGIN
  BOOL sunny = TRUE, warm = FALSE;
  INT temp = 72;

  print(("sunny AND warm = ", sunny AND warm, new line));
  print(("sunny OR warm  = ", sunny OR warm, new line));
  print(("NOT warm       = ", NOT warm, new line));

  IF temp > 60 AND temp < 80
  THEN print(("Temperature is comfortable.", new line))
  ELSE print(("Temperature is extreme.", new line))
  FI;

  IF NOT (temp = 0)
  THEN print(("Temperature is non-zero.", new line))
  FI
END

The IF ... THEN ... ELSE ... FI form is itself an expression in ALGOL 68 — the closing keyword is FI, the reverse of IF, a stylistic flourish that also distinguishes ALGOL 68 from its ALGOL 60 ancestor where END was overloaded for everything.

Assignment and Compound Assignment

In ALGOL 68, := is the assignment operator and it yields the reference to the variable being assigned, which means assignments can be chained or used in expressions. The operators +:=, -:=, *:=, /:=, %:=, and %*:= are the compound assignment shorthands.

Create a file named assignment.a68:

BEGIN
  INT count := 10;
  REAL balance := 100.0;

  count +:= 5;
  print(("count after +:= 5  -> ", count, new line));

  count -:= 3;
  print(("count after -:= 3  -> ", count, new line));

  count *:= 2;
  print(("count after *:= 2  -> ", count, new line));

  balance /:= 4.0;
  print(("balance after /:= 4.0 -> ", balance, new line));

  INT x, y, z;
  x := y := z := 0;
  print(("chained: x=", x, " y=", y, " z=", z, new line))
END

The chained assignment works because z := 0 evaluates to a reference to z (whose dereferenced value is 0), which is then assigned to y, and so on. This was a controversial design choice in 1968 but has since become standard in C and its descendants.

Defining Your Own Operator

ALGOL 68’s signature feature is user-defined operators. You declare an operator with the OP keyword and may set its precedence with PRIO. Here we define MAX as a binary operator returning the larger of two integers, at priority 8 (one above +).

Create a file named userop.a68:

BEGIN
  PRIO MAX = 8;
  OP MAX = (INT a, b) INT:
    IF a > b THEN a ELSE b FI;

  print(("3 MAX 7    = ", 3 MAX 7, new line));
  print(("10 MAX 4   = ", 10 MAX 4, new line));
  print(("2 + 3 MAX 5 = ", 2 + 3 MAX 5, new line))
END

Because MAX has higher priority than +, the last expression parses as 2 + (3 MAX 5) and yields 7. This single feature — and the way it composes with the mode system — is why ALGOL 68 is still cited in modern language design discussions nearly sixty years later.

Running with Docker

1
2
3
4
5
6
7
8
# Pull the official image
docker pull codearchaeology/algol68:latest

# Run each example
docker run --rm -v $(pwd):/app -w /app codearchaeology/algol68:latest operators.a68
docker run --rm -v $(pwd):/app -w /app codearchaeology/algol68:latest logical.a68
docker run --rm -v $(pwd):/app -w /app codearchaeology/algol68:latest assignment.a68
docker run --rm -v $(pwd):/app -w /app codearchaeology/algol68:latest userop.a68

Expected Output

Running operators.a68:

a =         +17, b =          +5
a + b   =         +22
a - b   =         +12
a * b   =         +85
a / b   = +3.40000000000000e  +0
a OVER b =          +3
a MOD b  =          +2
a ** 2   =        +289

Comparisons:
a = b   is F
a /= b  is T
a > b   is T
a <= b  is F

Running logical.a68:

sunny AND warm = F
sunny OR warm  = T
NOT warm       = T
Temperature is comfortable.
Temperature is non-zero.

Running assignment.a68:

count after +:= 5  ->         +15
count after -:= 3  ->         +12
count after *:= 2  ->         +24
balance after /:= 4.0 -> +2.50000000000000e  +1
chained: x=         +0 y=         +0 z=         +0

Running userop.a68:

3 MAX 7    =          +7
10 MAX 4   =         +10
2 + 3 MAX 5 =          +7

(Numeric formatting from Algol 68 Genie pads integers and prints reals in scientific notation by default; the values themselves are what matter.)

Key Concepts

  • / always yields REAL; use OVER (%) for truncating integer division and MOD (%*) for the remainder.
  • Logical operators are words: AND, OR, NOT — with &, \/, and ~ as symbolic synonyms. Both AND and OR short-circuit.
  • IF ... THEN ... ELSE ... FI is an expression, not just a statement, and can appear anywhere a value is expected.
  • Assignment := returns a reference, enabling chained assignments like x := y := z := 0.
  • Compound assignments (+:=, -:=, *:=, /:=, %:=, %*:=) mirror C’s +=, -=, etc., and ALGOL 68 invented them first.
  • Operators are user-extensible via OP and PRIO. You choose both the operator’s signature and its precedence (1 through 9).
  • Operator dispatch is structural: the compiler selects the operator definition matching the operand modes, an early form of static overloading.
  • Priority levels run 1 (lowest) to 9 (highest) in the standard prelude; placing a custom operator at priority 8 makes it bind tighter than + (priority 6) but looser than ** (priority 9).

Running Today

All examples can be run using Docker:

docker pull codearchaeology/algol68:latest
Last updated:

Comments

Loading comments...

Leave a Comment

2000 characters remaining