In Algol 60 procedure declarations, the 'specification' part was optional for by-name parameters. The specification is what gives (loosely speaking) the type of parameter - whether it's real, integer, boolean, an array of one of those, a procedure, a label, etc.

This to my modern sensibility is somewhat strange. It means the compiler has no information about the types of the parameters and therefore no information about legal invocations.

Nevertheless, the Revised Report does say: Any formal parameter may have restrictions on the   
type of the corresponding actual parameter associated with  
it (these restrictions may, or may not, be given through  
specifications in the procedure heading).   

So, we're in the position that the compiler can decide what actual parameters are legal, but we don't need to give it the information which would make it obvious (to the compiler and the reader).

What is the reason behind this state of affairs? I can guess at one or two: pure oversight when changes might still have been made, the possible inclination towards "open subroutines" that can be noticed elsewhere, or lack of agreement between participants.

The implementations I am most familiar with (KDF9: Whetstone Algol and Kidsgrove Algol) made specifications mandatory.

For the record, here is the syntax of procedure declarations, bold type omitted.

5.4 Procedure declarations  
5.4.1 Syntax.  

<formal parameter> ::= <identifier>  
<formal parameter list> ::= <formal parameter> | <formal parameter list>  
        <parameter delimiter><formal parameter>  
<formal parameter part> ::= <empty> | (<formal parameter list>)  
<identifier list> ::= <identifier> | <identifier list>,<identifier>  
<value part> ::= value <identifier list>; | <empty>  
<specifier> ::= string | <type> | array | <type> array | label | switch |  
        procedure | <type> procedure  
<specification part> ::= <empty> | <specifier><identifier list>; |  
        <specification part><specifier><identifier list>  
<procedure heading> ::= <procedure identifier><formal parameter part>;  
        <value part><specification part>  
<procedure body> ::= <statement> | <code>  
<procedure declaration> ::= procedure <procedure heading><procedure body> |  
        <type> procedure <procedure heading><procedure body>  
  • the possible inclination towards "open subroutines" is correct. The fact that undefined identifiers, e.g. references to other procedures, are allowed in procedure definitions is to wit. Such open subroutines are effectively templates. The issue is that a rare compiler would handle them correctly.
    – Leo B.
    Jul 14, 2021 at 22:21
  • Parameter specifications were even weirder in the original IAL; there seems to have been provision for partial functions ("currying").
    – texdr.aft
    Jul 14, 2021 at 22:42
  • 1
    Peter Naur's paper about Algol history describes the evolution of parameter specifications into their final form in Algol 60.
    – texdr.aft
    Jul 15, 2021 at 4:37
  • 1
    @texdr.aft - I've read the Naur paper in HOPL several times, and the transcript of the session, but for me it still doesn't really answer 'why'. I suppose the hangover from the substitution rule of IAL is the closest we'll get. On the other hand, the sheer confusion around parameter mechanisms at least show the state of the emerging art.
    – dave
    Jul 19, 2021 at 1:32
  • Perhaps the answer is to be found in the committee papers Naur cites, although they are not accessible as far as I can tell.
    – texdr.aft
    Jul 19, 2021 at 23:11

1 Answer 1


This small example demonstrates a use case for a procedure with unspecified parameters:

   1.  _BEGIN
   2.    _INTEGER _ARRAY X[0:10];
   3.    _REAL _ARRAY Y[1:20];
   4.    _PROCEDURE SUM(A, B, C, D);
   5.    _BEGIN _INTEGER I;
   6.      D := 0;
   7.      _FOR I := B _STEP 1 _UNTIL C _DO D := D + A[I];
   8.    _END;
   9.    _INTEGER I; _REAL R;
  10.    _FOR I := 0 _STEP 1 _UNTIL 10 _DO X[I] := I;
  11.    _FOR I := 1 _STEP 1 _UNTIL 20 _DO Y[I] := 1.0/I;
  12.    SUM(X, 0, 10, I);
  13.    SUM(Y, 1, 20, R);
  14.    OUTPUT(‘ZDDD’, I, ‘E’, R)
  15.  _END


           55 .3597739657⏨+01

The procedure SUM is called with an integer array with bounds [0:10] and a real array with bounds [1:20] passed as the first parameter in the first and the second invocation, respectively.

If the language had made parameter specifications mandatory, the procedure had to be replicated for each array type.

  • I understand the case, but don't see why that was sufficiently compelling - the requirement (assuming one instance of generated code) carry type information around so that each integer array element can be coerced to real.
    – dave
    Jul 15, 2021 at 11:44
  • @another-dave Regardless of code generation, this is a mechanism to declare a subroutine once and to use it with arrays of different element types and bounds, which would be impossible if exact types of parameters had to be specified.
    – Leo B.
    Jul 15, 2021 at 16:30
  • This concept sounds similar to "untyped var parameters" in Turbo Pascal, and it was often used for things like "write N bytes of an object to a file" or "copy N bytes of an object from one address to another". Even the only functions that could directly access the storage associated with such parameters would be compiler-supplied ones, it was nonetheless useful to be be able to pass such parameters to user functions that wrapped calls to the built-in ones.
    – supercat
    Jul 15, 2021 at 16:43
  • @LeoB - I suppose the follow-up question is "if it's such a good idea, why don't mainstream compiled languages today allow that?". (Like call-by-name, maybe, though I was quite fond of that).
    – dave
    Jul 15, 2021 at 22:32
  • 1
    @another-dave In C++, templated functions with auto formal parameters and lambda functions as actual parameters are a modern equivalent of unspecified parameter types and call-by-name, resp.
    – Leo B.
    Jul 16, 2021 at 0:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .