Procedures & Function Designators

A procedure declaration has a heading (name, formal parameters, value part, specifications) and a body (any statement — often a block):

14.1 Procedure declarations

A procedure declaration has a heading (name, formal parameters, value part, specifications) and a body (any statement — often a block):

Formal parameter list: (n).

Value part: 'value' n; lists parameters passed by value. All others are passed by name (Chapter 15).

Specification part: gives each parameter's kind: 'integer', 'real', 'boolean', 'array', 'integer' 'array', 'label', 'switch', 'procedure', 'real' 'procedure', 'string'.

The Revised Report allowed some specifications to be omitted; the Modified Report (and MARST) require all of them.

'procedure' print line(n);
    'value' n; 'integer' n;
'begin'
    'integer' i;
    'for' i := 1 'step' 1 'until' n 'do' outstring(1, "-");
    outstring(1, "\n")
'end';

14.2 Procedure statements

A call is just the procedure name with actual parameters:

print line(40);
print line(n + 2);

14.3 Function designators (typed procedures)

A procedure with a type returns a value by assigning to its own name inside the body:

Use it in expressions: c := hypot(3, 4);. Inside the body, the procedure name on the left of := sets the result; on the right it is a (recursive) call. If the body never assigns to the name, the result is undefined.

A typed procedure may also be called as a statement, discarding its result (useful when it has side effects).

'real' 'procedure' hypot(a, b);
    'value' a, b; 'real' a, b;
    hypot := sqrt(a * a + b * b);

'integer' 'procedure' max(a, b);
    'value' a, b; 'integer' a, b;
    max := 'if' a > b 'then' a 'else' b;

14.4 Parameterless procedures

A call is just random — indistinguishable from a variable reference. Parameterless procedures with side effects in expressions make evaluation order matter; ALGOL 60 does not define that order (Chapter 20).

'real' 'procedure' random;
'begin'
    'own' 'integer' seed;
    seed := seed * 1103 + 12345;
    seed := seed - 32768 * (seed % 32768);
    random := seed / 32768
'end';

14.5 Procedures as parameters

The specification 'real' 'procedure' f does not state f's parameters — ALGOL 60 has no procedure types with parameter lists, so a mismatched call is detected only at run time (or not at all). ALGOL 68 fixes this with modes like PROC (REAL) REAL.

'real' 'procedure' integrate(f, a, b, n);
    'value' a, b, n; 'real' a, b; 'integer' n;
    'real' 'procedure' f;
'begin'
    'integer' i; 'real' h, s;
    h := (b - a) / n;
    s := (f(a) + f(b)) / 2;
    'for' i := 1 'step' 1 'until' n - 1 'do' s := s + f(a + i * h);
    integrate := s * h
'end';

'real' 'procedure' square(x); 'value' x; 'real' x; square := x * x;

'comment' ... integrate(square, 0, 1, 100) is approximately 1/3;

14.6 String parameters

Strings can be passed only to procedures whose formal is specified 'string', and the only thing such a procedure can do with it is pass it on (ultimately to a code procedure such as outstring):

'procedure' banner(s); 'string' s;
'begin'
    outstring(1, "*** "); outstring(1, s); outstring(1, " ***\n")
'end';

14.7 Code procedures

The Revised Report allows procedure bodies to be written in non-ALGOL "code" — implementation-defined. This is how I/O, mathematical libraries and machine-specific facilities were provided. MARST's runtime library plays this role.