John Kominek (firstname.lastname@example.org) wrote: Sprinkled throughout SRC m3 you'll find "constant" variables exported in interfaces. For instance,
VAR (*CONST*) Grain: LONGREAL;
where Grain is assigned during module initialization. Instead, did the modula-3 designers consider doing this.
READONLY Grain: LONGREAL;
Here the keyword permits only exporting modules to modify the Grain variable. Is there a problem with this proposal? The READONLY keyword is successfully used at procedure boundaries, so why not also at interface boundaries?
Bill Kalsow replies:
A problem with this proposal is that any module can claim to export the interface containing the variable, hence any module could modify the variable. Note that CONST says more than just READONLY. CONST implies that the variable should not be modified by clients and that once it is initialized, it won't be changed later by the implementation. READONLY would only mean that clients should not modify the variable. IMO, the "right" solution would have been to allow:
INTERFACE Foo; CONST x: T; MODULE Foo; CONST x: T := <value>;
In the same way it checks revelations for opaque types, the compiler could check that only one module provided a value for the constant. But, this proposal doesn't quite hang together either. Consider this example:
CONST x: INTEGER; VAR v: [0..x];
The language definition says that "v"s definition is illegal if "x < 0" because its type is "empty". The system could refuse to run the program by delaying the check until it had seem the corresponding implementation module. But, I think you'll agree that it could quickly turn into a mess. The most flexible handling of opacity I've seen is in Christian Collberg's PhD Thesis, "Flexible Encapsulation". It was published Dec 5, 1992 by the CS Dept at Lund University, Lund Sweden. If I remember correctly, his system was capable of deferring all checks and decisions imposed by opaque declarations until link time.