[Oberon] Oberon and closures

Thomas Frey thomas.frey at alumni.ethz.ch
Thu Oct 30 20:58:26 MET 2008

In Active Oberon we have an additional way of simulating (strongly 
typed) closures.

the reachable state of the closure function is stored in the fields of a 
local OBJECT type (POINTER TO RECORD) (Note : Bound variables in 
functional languages are "read only", here we rely on the programmer)
The closure itself is then a delegate procedure variable bound to a 
method of an instance of the local OBJECT (class). The delegate 
encapsulates the code and the state (as a closure)

The advantage of this way of doing a "closure" is that the computational 
effort is visible to the programmer and not hidden behind the scene as 
in other languages. (Note : Using objects and delegates normally allows 
for more natural solutions than the following example which tries to 
mimic closures as closely as possible)

MODULE Closure; (** AUTHOR "tf"; PURPOSE "closure simulation"; *)

   Out := KernelLog;
   Printer = PROCEDURE {DELEGATE} ();

(* creates a closure *)
PROCEDURE CreatePrinter(nr : LONGINT): Printer;
   (* container for the accessed scope *)
   PrinterClosure = OBJECT
   VAR nr : LONGINT; (* state *)

     (* functionality, able to access the "copied scope"*)
     PROCEDURE Print;
       Out.Int(nr, 0); Out.Ln;
     END Print;
   END PrinterClosure;

    closure : PrinterClosure;
   (* create the container for the bound variables *)
   (* "bind" the variables *)
   closure.nr := nr;
   (* return the closure *)
   RETURN closure.Print;
END CreatePrinter;

VAR print : Printer;
   print := CreatePrinter(5);
   (* use the closure *)
END Test;

END Closure.



B. Smith-Mannschott schrieb:
> On Oct 30, 2008, at 09:16, Bob Walkden wrote:
>>>> So, yes, you can create a closure in Oberon.
>>> Well, no, not really.  The Module being a single giant closure over
>>> all the procedures defined in it is *not* what is generally meant by
>>> "closure".  In particular, languages which support closures generally
>>> allow something like this:
>>> MODULE Example;
>>> (* my oberon's a little rusty *)
>>> TYPE
>>>   Printer = PROCEDURE();
>>> VAR
>>>   p, q: Printer;
>>> PROCEDURE CreateNumberPrinter(n: INTEGER): Printer;
>>>     PROCEDURE PrintingProcedure;
>>>     BEGIN Out.WriteInt(n)
>>>     END PrintingProcedure;
>>>     RETURN PrintingProcedure
>>> END CreateNumberPrinter;
>>>   p := CreateNumberPrinter(1);
>>>   q := CreateNumberPrinter(2);
>>>   p; (* prints 1 *)
>>>   q; (* prints 2 *)
>>> END Example;
>>> Note that each invocation of CreateNumberPrinter creates a new closure
>>> over the nested procedure PrintingProcedure. In fact the fact that
>>> Pascal/Modula/Oberon only allows top-level procedures as procedure
>>> values appears to be a direct result of the fact that the language
>>> doesn't support proper closures. (In order to support closures as
>>> above you need something more involved than a simple stack as an
>>> instance of PrintingProcedure needs to find its "n", even after the
>>> CreateNumberPrinter that created it is no longer active on the stack).
>> "the language doesn't support proper closures"
>> What are the benefits of supporting this? It doesn't feel to me as 
>> though it is
>> in 'the spirit of Oberon'. It feels like the kind of accident waiting 
>> to happen
>> that Prof. Wirth preferred to avoid.
> Yes supporting full closures would have complicated the compiler and/or
> the runtime system considerably and wouldn't have been in Wirth's style.
> By choosing not to indulge in this feature he was able to keep his 
> languages
> and compilers far smaller and simpler than they otherwise would have been.
> There's no law that says that every language must support closures (or
> tail call eliminiation, or mult-methods, continuations, or ...)  and I for
> one am glad that Wirth chose to keep Oberon simple.
> // Ben
> -- 
> Oberon at lists.inf.ethz.ch mailing list for ETH Oberon and related systems
> https://lists.inf.ethz.ch/mailman/listinfo/oberon

More information about the Oberon mailing list