[Oberon] Unneeded restrictions on local procedures

August Karlstrom fusionfile at gmail.com
Thu Dec 21 21:02:09 CET 2023


On 2023-12-20 23:39, Joerg wrote:
> If I understood August correctly, his idea was to get rid of restrictions not invent new ones.
> We could indeed tell the compiler to allow assigments only to local procedure variables, but I think this restriction is not needed.

When using higher order procedures it would be natural to pass locally 
declared (often small) procedures. In the following example the 
procedures Init, Print, Odd and Sum would be more naturally declared as 
local procedures in Test.

MODULE test;

    IMPORT Out;

    TYPE
       Selector = PROCEDURE (x: INTEGER): BOOLEAN;
       Applicator = PROCEDURE (i: INTEGER; VAR x: INTEGER);
       Reducer = PROCEDURE (acc, x: INTEGER): INTEGER;

    PROCEDURE Filter(wanted: Selector; VAR a: ARRAY OF INTEGER; VAR n: 
INTEGER);
       VAR i, j: INTEGER;
    BEGIN
       j := 0;
       FOR i := 0 TO n - 1 DO
          IF wanted(a[i]) THEN
             a[j] := a[i];
             INC(j)
          END
       END;
       n := j
    END Filter;

    PROCEDURE Apply(f: Applicator; VAR a: ARRAY OF INTEGER; n: INTEGER);
       VAR i: INTEGER;
    BEGIN
       FOR i := 0 TO n - 1 DO
          f(i, a[i])
       END
    END Apply;

    PROCEDURE Reduction(f: Reducer; acc: INTEGER; a: ARRAY OF INTEGER; 
n: INTEGER): INTEGER;
       VAR i: INTEGER;
    BEGIN
       FOR i := 0 TO n - 1 DO
          acc := f(acc, a[i])
       END
    RETURN acc
    END Reduction;

    PROCEDURE Init(i: INTEGER; VAR x: INTEGER); (*should be local to Test*)
    BEGIN
       x := i + 1
    END Init;

    PROCEDURE Print(i: INTEGER; VAR x: INTEGER); (*should be local to Test*)
    BEGIN
       Out.Int(x, 0);
       Out.Char(" ")
    END Print;

    PROCEDURE Odd(x: INTEGER): BOOLEAN; (*should be local to Test*)
    RETURN ODD(x)
    END Odd;

    PROCEDURE Sum(acc, x: INTEGER): INTEGER; (*should be local to Test*)
    RETURN acc + x
    END Sum;

    PROCEDURE Test;
       VAR a: ARRAY 10 OF INTEGER;
          n, s: INTEGER;
    BEGIN
       Apply(Init, a, LEN(a));
       n := LEN(a);
       Filter(Odd, a, n);
       Apply(Print, a, n);
       Out.Ln;
       s := Reduction(Sum, 0, a, n);
       Out.Int(s, 0);
       Out.Ln
    END Test;

BEGIN
    Test
END test.


More information about the Oberon mailing list