Beginner

Variables and Types in ALGOL 68

Learn about ALGOL 68's powerful mode system — its unique approach to variables, types, and type composition with practical Docker-ready examples

Introduction

ALGOL 68 takes a distinctive approach to variables and types through what it calls its mode system. Rather than using the word “type,” ALGOL 68 uses “mode” to describe the nature of a value. This terminology signals that the type system is richer and more orthogonal than in most languages of its era — or even many languages that followed.

In ALGOL 68, every value has a mode, and the language enforces these modes strictly at compile time. This is static, strong, structural typing in action: the compiler checks modes before the program runs, type coercions follow precise rules, and the structure of a mode determines compatibility, not its name. Understanding modes is the key to understanding ALGOL 68.

What makes this particularly interesting is how ALGOL 68’s mode system prefigured features that became widespread only decades later: structural typing, union types (called “united modes”), and user-definable type synonyms (via MODE declarations). This tutorial covers the foundational mode concepts you will encounter in every ALGOL 68 program.

Declaring Variables and Basic Modes

In ALGOL 68, a variable declaration places the mode before the name. Assignment uses := (the walrus operator, though ALGOL 68 predates that name). The basic primitive modes are:

  • INT — integer (whole number)
  • REAL — floating-point number
  • BOOL — boolean (TRUE or FALSE)
  • CHAR — single character
  • STRING — a sequence of characters (technically a flexible array of CHAR)

Create a file named variables.a68:

BEGIN
  # Integer variables #
  INT count := 42;
  INT year := 1968;

  # Real (floating-point) variables #
  REAL pi := 3.14159265;
  REAL temperature := -17.5;

  # Boolean variables #
  BOOL is historic := TRUE;
  BOOL is mainstream := FALSE;

  # Character and string variables #
  CHAR initial := "A";
  STRING language name := "ALGOL 68";

  # Print the values #
  print(("count = ", count, new line));
  print(("year = ", year, new line));
  print(("pi = ", pi, new line));
  print(("temperature = ", temperature, new line));
  print(("is historic = ", is historic, new line));
  print(("initial = ", initial, new line));
  print(("language name = ", language name, new line))
END

A few ALGOL 68 syntax notes:

  • # begins and ends comments (ALGOL 68 uses # as a comment delimiter)
  • := is the assignment operator; = is used for equality testing only
  • Semicolons separate statements within a BEGIN...END block
  • Identifiers may contain spaceslanguage name is a single identifier, which is a unique ALGOL 68 feature

Constants and Identity Relations

ALGOL 68 makes a clear distinction between variables (which hold references to values) and constants (identity relations that directly name a value). A constant is declared with = instead of :=:

Create a file named variables_constants.a68:

BEGIN
  # Constants (identity relations) — cannot be reassigned #
  INT max count = 100;
  REAL avogadro = 6.02214076e23;
  BOOL debug mode = FALSE;
  STRING version = "3.1.2";

  # Variables — can be reassigned #
  INT counter := 0;
  counter := counter + 1;
  counter := counter + 1;

  print(("max count = ", max count, new line));
  print(("avogadro = ", avogadro, new line));
  print(("version = ", version, new line));
  print(("counter after increments = ", counter, new line));

  # ALGOL 68 enforces the distinction:
  # max count := 200  would be a compile error — max count is not a variable #
  print(("Constants cannot be reassigned — enforced at compile time", new line))
END

This distinction reflects ALGOL 68’s careful separation between l-values (locations in memory) and r-values (values). Variables are references that can be dereferenced and updated; constants name values directly. ALGOL 68 was one of the first languages to articulate this distinction formally.

User-Defined Modes (Type Synonyms)

One of ALGOL 68’s most powerful features is the MODE declaration, which creates a new name for any existing mode. This is structural typing: a MODE declaration creates an alias, not a distinct incompatible type.

Create a file named variables_modes.a68:

BEGIN
  # Define mode synonyms #
  MODE TEMPERATURE = REAL;
  MODE COUNT = INT;
  MODE NAME = STRING;
  MODE FLAG = BOOL;

  # Use the new mode names #
  TEMPERATURE boiling point = 100.0;
  TEMPERATURE freezing point = 0.0;
  COUNT population := 8000000000;
  NAME language = "ALGOL 68";
  FLAG is active = TRUE;

  print(("Boiling point: ", boiling point, " C", new line));
  print(("Freezing point: ", freezing point, " C", new line));
  print(("World population: ", population, new line));
  print(("Language: ", language, new line));
  print(("Active: ", is active, new line));

  # Because MODE creates structural aliases, TEMPERATURE and REAL are compatible #
  REAL raw temp := boiling point;
  print(("Raw temp (as REAL): ", raw temp, new line))
END

User-defined modes make programs self-documenting and reveal intent. A TEMPERATURE variable communicates far more than a bare REAL.

Type Coercions and the Coercion Hierarchy

ALGOL 68’s type system includes a set of precisely defined coercions — automatic conversions the compiler performs when context requires it. These are not implicit casts; they follow strict rules depending on the “syntactic position” (context) of an expression.

The key coercions relevant to variables are:

  • Widening: INT widens to REAL in numeric contexts
  • Dereferencing: A variable (reference) is automatically dereferenced to yield its value

Create a file named variables_coercions.a68:

BEGIN
  # Widening: INT is automatically coerced to REAL where needed #
  INT whole := 7;
  REAL fraction := whole;   # INT widened to REAL automatically #

  print(("INT value: ", whole, new line));
  print(("Widened to REAL: ", fraction, new line));

  # Explicit conversion using standard procedures #
  REAL pi approx := 3.14159;
  INT truncated = ENTIER pi approx;   # ENTIER truncates toward negative infinity #
  INT rounded = ROUND pi approx;      # ROUND rounds to nearest integer #

  print(("pi approx: ", pi approx, new line));
  print(("ENTIER (truncate): ", truncated, new line));
  print(("ROUND (nearest): ", rounded, new line));

  # String and character operations #
  STRING greeting := "Hello";
  INT length = UPB greeting;   # UPB gives the upper bound (length) of a string #

  print(("Greeting: ", greeting, new line));
  print(("Length: ", length, new line));

  # Character arithmetic #
  CHAR letter a = "a";
  INT char code = ABS letter a;   # ABS converts a CHAR to its integer code #
  CHAR next letter = REPR (char code + 1);   # REPR converts back to CHAR #

  print(("Letter: ", letter a, new line));
  print(("Char code: ", char code, new line));
  print(("Next letter: ", next letter, new line))
END

ENTIER (from French for “whole”) and ROUND are ALGOL 68’s standard conversion procedures — remnants of the language’s European academic origins. ABS and REPR handle the CHAR/INT bridge.

Running with Docker

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Pull the image
docker pull codearchaeology/algol68:latest

# Run the basic variables example
docker run --rm -v $(pwd):/app -w /app codearchaeology/algol68:latest variables.a68

# Run the constants example
docker run --rm -v $(pwd):/app -w /app codearchaeology/algol68:latest variables_constants.a68

# Run the user-defined modes example
docker run --rm -v $(pwd):/app -w /app codearchaeology/algol68:latest variables_modes.a68

# Run the coercions example
docker run --rm -v $(pwd):/app -w /app codearchaeology/algol68:latest variables_coercions.a68

Expected Output

Running variables.a68:

count =        +42
year =       +1968
pi = +3.14159265000000e  +0
temperature = -1.75000000000000e  +1
is historic = T
initial = A
language name = ALGOL 68

Running variables_constants.a68:

max count =       +100
avogadro = +6.02214076000000e +23
version = 3.1.2
counter after increments =         +2
Constants cannot be reassigned — enforced at compile time

Running variables_modes.a68:

Boiling point: +1.00000000000000e  +2 C
Freezing point: +0.00000000000000e  +0 C
World population:  +8000000000
Language: ALGOL 68
Active: T
Raw temp (as REAL): +1.00000000000000e  +2

Running variables_coercions.a68:

INT value:         +7
Widened to REAL: +7.00000000000000e  +0
pi approx: +3.14159000000000e  +0
ENTIER (truncate):         +3
ROUND (nearest):         +3
Greeting: Hello
Length:         +5
Letter: a
Char code:        +97
Next letter: b

Note on ALGOL 68 output format: Algol 68 Genie prints integers with leading spaces and a +/- sign, and reals in scientific notation with explicit sign on the exponent. This is standard ALGOL 68 behavior — the printf procedure with format strings gives more control over formatting.

Key Concepts

  • Modes, not types: ALGOL 68 calls its types “modes” — INT, REAL, BOOL, CHAR, and STRING are the fundamental primitive modes
  • Declaration syntax: Mode precedes name — INT count := 42 not count: int = 42 or int count = 42
  • Variables vs. constants: := creates a mutable variable; = creates an identity relation (constant) — the compiler enforces this distinction
  • Identifiers with spaces: ALGOL 68 uniquely allows spaces in identifiers — language name is a single identifier, not two tokens
  • MODE declarations: Create structural aliases for any mode; useful for self-documenting code without creating incompatible types
  • Coercion hierarchy: INT widens to REAL automatically where needed; explicit conversion uses ENTIER, ROUND, ABS, and REPR
  • ENTIER vs. ROUND: ENTIER truncates toward negative infinity (floor), ROUND rounds to nearest integer — both convert REAL to INT
  • String length via UPB: Strings are flexible arrays of CHAR; UPB (upper bound) returns the length, a pattern that extends to all ALGOL 68 arrays

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