An else clause was added to
FORTRAN's IF.
E.g.,
if a > b then
a := b;
else
b := a;
for has a number of variants:
for i := 1 step 2 until N do
a[i] := b[i];
for newGuess := Improve( oldGuess )
while abs( newGuess - oldGuess ) > 0.0001 do
oldGuess := newGuess;
for days := 31,
if mod( year, 4 ) = 0 then 29 else 28,
31, 30, 31, 30, 31, 31, 30, 31, 30, 31 do
. . .
for i := 3, 7,
11 step 1 until 16,
i ÷ 2 while i >= 1,
2 step i until 32 do
print( i );
The last example prints
3 7 11 12 13 14 15 16 8 4 2 1 2 4 8 16 32
See footnote regarding an error in the textbook concerning this example.
In general, a for-loop generates a sequence of values to be assigned successively to the controlled variable.
This is not exactly definite iteration -- loop parameter expressions are re-evaluated on each iteration, and the loop body may change the parameter values.
The expense of re-evaluating for-loop parameters on each iteration is born by all loops, even though changing parameters in the body of a loop is relatively uncommon.
The switch declaration is like an array of labels.
E.g.,
begin
switch status = single, married, divorced, widowed;
:
goto status[ i ];
single: <"single" case>
goto done;
married: <"married" case>
goto done;
divorced: <"divorced" case>
goto done;
widowed: <"widowed" case>
done: . . .
end
Switch elements may be conditional expressions evaluated at the time of the goto.
E.g.,
begin
switch S = L, if i > 0 then M else N, Q;
goto S[ j ];
end
If j = 2, the destination depends on the current value of i.
begin-end pairs are used for two purposes:
Compound statement -- Brackets any number of statements into the syntactic
equivalent of a single statement.
E.g.,
begin
<statement 1>
<statement 2>
:
<statement n>
end
All control structures are defined to govern a single statement: for, then, else, procedure.
The programmer must remember to add a begin-end pair if changing from a single to several statements.
Block -- Defines a nested scope with local variables.
A block requires an activation record; a compound statement does not.
This is a violation of the Orthogonality Principle.
The compiler must determine whether or not any variables or procedures are declared in a block to determine whether or not to generate block entry/exit code.
Hierarchical structure led to structured programming.
Naur, Dijkstra, and Landin experimented with goto-less programming.
Dijkstra's " Go To Statement Considered Harmful" suggested the elimination of goto to lessen the "conceptual gap" between the static and dynamic structure (the Structure Principle).
This programming language issue became (and still is) the focal point of a wider issue in programming methodology.
Algol supports two parameter passing mechanisms:
integer procedure fac( n );
value n;
integer n;
fac := if n = 0 then 1 else n * fac( n - 1 );
| + | Secure: input mode only. |
| - | Expensive for passing arrays (in both time and space). |
procedure inc( n );
integer n;
n := n + 1;
| Called as: | Procedure body becomes: |
|---|---|
| inc( i ) | i := i + 1 |
| inc( A[k] ) | A[k] := A[k] + 1 |
Actual parameters are re-evaluated on every reference.
| FORTRAN | Algol |
|---|---|
SUBROUTINE S(L, K) K=2 L=0 RETURN END : A(1)=A(2)=1 I=1 CALL S(A(I), I) |
procedure S(L, K)
integer L, K;
begin
K := 2;
L := 0;
end;
:
a[1] := a[2] := 1;
i := 1;
S( a[i], i );
|
| In effect: | |
SUBROUTINE S(L, K) I=2 A[1]=0 RETURN END |
procedure S(L, K)
integer L, K;
begin
i := 2;
a[i] := 0; i.e., a[2]
end;
|
Implemented by passing the address of a thunk -- a piece of code produced by the compiler which (re-)computes the address of the actual parameter each time it is referenced.
Jensen's device -- uses the property that name parameters are re-evaluated
on every reference to implement mathematical sigma notation, simply.
E.g., evaluating x = i=1Σn Vi:
| C | Algol |
|---|---|
double sum( int l, int u,
double a[] )
{
int k;
double s = 0;
for ( k = l; k <= u; k++ )
s = s + a[k];
return s;
}
:
x = sum( 1, n, V );
|
real procedure Sum (k, l, u, ak )
value l, u;
integer k, l, u; real ak;
begin
real S; S := 0;
for k := l step 1 until u do
S := S + ak;
Sum := S;
end;
:
x := Sum( i, 1, n, V[i] );
|
| In effect: | |
int k;
double s = 0;
for ( k = 1; k <= n; k++ )
s = s + V[k];
x = s;
|
begin
real S; S := 0;
for i := 1 step 1 until n do
S := S + V[i];
x := S;
end;
|
Procedure calls can be passed as actual parameters.
Late inspection time gives unreliable results.
E.g., Consider this simple swap procedure:
procedure Swap ( x, y )
integer x, y;
begin
integer t;
t := x;
x := y;
y := t;
end;
Apply this procedure using the "copy rule" (a conceptual model of how call-by-name works) as in the following examples:
Swap( i, j ); Swap( A[i], i ); Swap( i, A[i] );
Note:
The example of an Algol for-loop given in the textbook (p. 138) uses the operator '/' instead of '÷' in the while clause, which actually causes the loop to print
3 7 11 12 13 14 15 16 9 5 3 2 1 1 1 1 . . .
Three features of the specification of Algol 60 interact to produce this list of values:
The step ... until statement steps the value of the loop control variable until it has passed the specified termination value, so i has the value 17 after the clause '11 step 1 until 16' finishes and before the clause 'i / 2 while i >= 1' starts (but the statement controlled by the loop is not executed for i as 17).
The '/' operator in Algol operates on either real or integer arguments, but returns a real result. (The '÷' operator, on the other hand, operates only on integer arguments and returns an integer result.) This implies that i / 2 has the value 8.5 the first time the while clause is executed.
The Revised Report on the Algorithmic Language Algol 60 specifies that a real value is to be rounded (not truncated, as in C and related languages) if it is to be assigned to an integer variable.
Copyright © 2000, 2001 Jonathan Mohr