Variables and Types in ALGOL 60
Learn about variables, data types, and type declarations in ALGOL 60 with practical Docker-ready examples
ALGOL 60’s type system was genuinely revolutionary for 1960. At a time when FORTRAN distinguished INTEGER from REAL mostly by name convention, ALGOL 60 introduced a formal, compiler-enforced static type system with explicit declarations. Every variable must be declared before it is used, the compiler knows each variable’s type at compile time, and mixing incompatible types is a compile error — concepts that became the backbone of Pascal, C, Ada, and virtually every statically-typed language that followed.
ALGOL 60 defines three core scalar types: integer (whole numbers), real (floating-point numbers), and Boolean (logical true/false values). Strings in GNU MARST are handled as literals for output; the language was not originally designed around string manipulation. ALGOL 60 also supports arrays — including the groundbreaking innovation of arrays with runtime-computed bounds — which were a major departure from the fixed-dimension arrays of FORTRAN.
Because ALGOL 60 is an imperative, procedural, structured language, its variables work exactly as you would expect from that paradigm: you declare them, assign them values, reassign them, and they exist for the lifetime of the enclosing block. There is no type inference, no dynamic typing, and no garbage collector — variables are stack-allocated within their lexical scope.
Declaring Integer and Real Variables
All variable declarations appear at the top of a block, before the first executable statement. This separation between declarations and executable code is one of ALGOL 60’s defining structural features — a convention that Pascal and Ada preserved directly.
Create a file named variables.alg:
begin
integer count, max_size, negative;
real pi, temperature, ratio;
comment Assign integer values;
count := 42;
max_size := 1000000;
negative := -17;
comment Assign real values;
pi := 3.14159;
temperature := 98.6;
ratio := 2.71828;
comment Output integer values;
outstring(1, "=== Integer Variables ===\n");
outstring(1, "count = "); outinteger(1, count); outstring(1, "\n");
outstring(1, "max_size = "); outinteger(1, max_size); outstring(1, "\n");
outstring(1, "negative = "); outinteger(1, negative); outstring(1, "\n");
comment Output real values;
outstring(1, "\n=== Real Variables ===\n");
outstring(1, "pi = "); outreal(1, pi); outstring(1, "\n");
outstring(1, "temperature = "); outreal(1, temperature); outstring(1, "\n");
outstring(1, "ratio = "); outreal(1, ratio); outstring(1, "\n")
end
A few things to notice here:
integerandrealare type keywords — lowercase, no stropping needed in GNU MARST- Multiple variables of the same type are listed after the type keyword, comma-separated
:=is the assignment operator;=is used only for equality comparison- Declarations come before the first statement — you cannot declare in the middle of a block
- The last statement in a block does not end with a semicolon (semicolons are separators, not terminators)
Boolean Variables and Logical Expressions
ALGOL 60 introduced Boolean as a first-class type, named after the mathematician George Boole. Boolean values are true and false (lowercase in GNU MARST), and the logical operators are ∧ (and), ∨ (or), and ¬ (not) in the original report. GNU MARST uses ASCII alternatives: and, or, not, = (equivalence), and ⊃ or imp (implication).
Create a file named variables_bool.alg:
begin
Boolean is_active, is_done, result;
integer x, y;
is_active := true;
is_done := false;
x := 10;
y := 20;
comment Boolean expressions using comparisons;
result := x < y;
outstring(1, "=== Boolean Variables ===\n");
outstring(1, "is_active = "); outstring(1, if is_active then "true" else "false"); outstring(1, "\n");
outstring(1, "is_done = "); outstring(1, if is_done then "true" else "false"); outstring(1, "\n");
outstring(1, "x < y = "); outstring(1, if result then "true" else "false"); outstring(1, "\n");
comment Logical operators;
outstring(1, "\n=== Logical Operations ===\n");
outstring(1, "true and false = ");
outstring(1, if true and false then "true" else "false"); outstring(1, "\n");
outstring(1, "true or false = ");
outstring(1, if true or false then "true" else "false"); outstring(1, "\n");
outstring(1, "not true = ");
outstring(1, if not true then "true" else "false"); outstring(1, "\n");
comment Integer arithmetic in context;
outstring(1, "\n=== Integer Arithmetic ===\n");
outstring(1, "x + y = "); outinteger(1, x + y); outstring(1, "\n");
outstring(1, "x * y = "); outinteger(1, x * y); outstring(1, "\n");
outstring(1, "y / x = "); outinteger(1, y / x); outstring(1, "\n");
outstring(1, "y - x = "); outinteger(1, y - x); outstring(1, "\n");
comment Power operator uses double star ** in MARST;
outstring(1, "x ** 2 = "); outinteger(1, x ** 2); outstring(1, "\n")
end
The if ... then ... else ... construct used inside outstring calls is ALGOL 60’s conditional expression — an expression that yields a value based on a Boolean condition. It is not a statement; it produces a result that can be used anywhere an expression is valid. This feature predates the ternary operator ? : that C borrowed for the same purpose.
Arrays in ALGOL 60
Arrays are one of ALGOL 60’s most celebrated features. Unlike FORTRAN, which required array sizes to be known at compile time, ALGOL 60 allowed array bounds to be computed at runtime — a radical innovation in 1960. Arrays are declared with the array keyword followed by a subscript range.
Create a file named variables_arrays.alg:
begin
integer n, i, sum;
real average;
integer array scores[1:5];
comment Initialize array elements;
n := 5;
scores[1] := 85;
scores[2] := 92;
scores[3] := 78;
scores[4] := 95;
scores[5] := 88;
comment Calculate the sum;
sum := 0;
for i := 1 step 1 until n do
sum := sum + scores[i];
comment Calculate average - promote sum to real before dividing;
average := (sum + 0.0) / n;
outstring(1, "=== Array Example ===\n");
outstring(1, "Scores: ");
for i := 1 step 1 until n do
begin
outinteger(1, scores[i]);
if i < n then outstring(1, ", ")
end;
outstring(1, "\n");
outstring(1, "Sum = "); outinteger(1, sum); outstring(1, "\n");
outstring(1, "Average = "); outreal(1, average); outstring(1, "\n")
end
Key array facts in ALGOL 60:
integer array scores[1:5]declares an integer array with indices 1 through 5 (1-indexed by convention, though any integer range is valid)- Array element assignment and access use
[and]brackets - The type keyword (
integer,real,Boolean) precedesarrayto specify element type; barearraywithout a type defaults toreal - Use
integer arrayorreal arrayto declare typed arrays explicitly
Type Conversion Between Integer and Real
ALGOL 60 requires explicit awareness of integer versus real arithmetic. Division of two integers performs integer division (truncation toward zero). Mixing an integer and a real in an expression typically promotes the result to real. When you need to convert between types explicitly, you can use arithmetic tricks or rely on the type coercion rules.
Create a file named variables_types.alg:
begin
integer a, b, int_result;
real x, y, real_result;
a := 7;
b := 2;
x := 7.0;
y := 2.0;
comment Integer division truncates;
int_result := a / b;
comment Real division gives fractional result;
real_result := x / y;
outstring(1, "=== Type Behavior ===\n");
outstring(1, "a = "); outinteger(1, a); outstring(1, " (integer)\n");
outstring(1, "x = "); outreal(1, x); outstring(1, " (real)\n");
outstring(1, "\n=== Division Results ===\n");
outstring(1, "7 / 2 (integer) = "); outinteger(1, int_result); outstring(1, "\n");
outstring(1, "7.0 / 2.0 (real) = "); outreal(1, real_result); outstring(1, "\n");
comment entier() converts real to integer (floor function);
real_result := 3.75;
outstring(1, "\n=== entier() Function ===\n");
outstring(1, "entier(3.75) = "); outinteger(1, entier(real_result)); outstring(1, "\n");
outstring(1, "entier(-3.75) = "); outinteger(1, entier(-real_result)); outstring(1, "\n");
comment Integer value used in real context - automatically widened;
real_result := a;
outstring(1, "\n=== Widening ===\n");
outstring(1, "integer a = "); outinteger(1, a); outstring(1, "\n");
outstring(1, "as real = "); outreal(1, real_result); outstring(1, "\n")
end
The entier() function is the ALGOL 60 standard way to convert a real to an integer — it computes the floor (greatest integer not exceeding the value). Assigning an integer expression to a real variable widens the value automatically.
Running with Docker
| |
Expected Output
Output from variables.alg:
=== Integer Variables ===
count = 42
max_size = 1000000
negative = -17
=== Real Variables ===
pi = 3.14159
temperature = 98.6
ratio = 2.71828
Output from variables_bool.alg:
=== Boolean Variables ===
is_active = true
is_done = false
x < y = true
=== Logical Operations ===
true and false = false
true or false = true
not true = false
=== Integer Arithmetic ===
x + y = 30
x * y = 200
y / x = 2
y - x = 10
x ** 2 = 100
Output from variables_arrays.alg:
=== Array Example ===
Scores: 85, 92, 78, 95, 88
Sum = 438
Average = 87.6
Output from variables_types.alg:
=== Type Behavior ===
a = 7 (integer)
x = 7 (real)
=== Division Results ===
7 / 2 (integer) = 3
7.0 / 2.0 (real) = 3.5
=== entier() Function ===
entier(3.75) = 3
entier(-3.75) = -4
=== Widening ===
integer a = 7
as real = 7
Key Concepts
- Declarations precede statements — All variables must be declared at the top of a block, before any executable code. This separation is structural and enforced, not a convention.
- Three core scalar types —
integer,real, andBooleancover the fundamental data needs ALGOL 60 was designed for: numeric computing and logical decision-making. :=is assignment,=is equality — The distinction between:=(gets the value of) and=(is equal to) was introduced by ALGOL 60 and carried forward into Pascal, Ada, and Modula-2. C chose=for assignment instead, creating decades of confusion.- Integer division truncates — Dividing two
integervalues performs truncation; userealvariables for fractional results. entier()is the floor function — ALGOL 60 providesentier(x)to convert a real to its integer floor; this is the standard way to convert from real to integer.- Dynamic array bounds — ALGOL 60 was the first major language to allow array bounds computed at runtime, a significant advance over FORTRAN’s compile-time-only arrays. Bounds are written as
[lower:upper]. - Conditional expressions return values —
if B then E1 else E2is an expression, not just a statement. It evaluates to eitherE1orE2based onB, allowing it to appear anywhere a value is needed. - Lexical scope by block — Variables are scoped to the
begin...endblock in which they are declared. Nested blocks can declare their own variables that shadow outer ones — the lexical scoping rules that became standard in virtually all modern languages.
Running Today
All examples can be run using Docker:
docker pull codearchaeology/algol60:latest