Martin Odersky wrote:
..
> ... A good way to look at it is by comparing the
> role of record field labels with the role of other identifiers. In ML
> this correspondence made is very clear by writing the selection of
> field "l" as "#l r", i.e. the label acts like a function
> identifier. ...

I urge designers to look beyond program construction alone.  Most of the
cost of _real_ programs is incurred in post-construction modification and
maintenance.

There are distinct advantages for software maintenance in having the reference
to record fields and functions syntactically equivalent.  Geschke and
Mitchell wrote eloquently on this subject in "On the problem of uniform
references to data structures", IEEE TSE SE-1, 2 (June 75).

To allow the program's author to express some of his intent to subsequent
readers, it is useful as well (but not necessary) to allow all of
argument.function, record.field, function(argument) and field(record) to
coexist (put in your own favorite punctuation or lack thereof).

The important issue is to allow one to change the _representation_ of a
concept by changing its _declaration_, but not thereby require one to
change _all_the_references_.  In "On the criteria for decomposing programs
into modules" (CACM, Dec 72), David Parnas (constraining himself by then-
currently-popular language designs) argued this should be achieved by
encapsulating each resource in a procedure.  This argument has survived to
the present time in software engineering curricula, but the underlying reason,
as spelled out in the first sentence of this paragraph, has been forgotten.

In languages that allow updating state, it is useful as well to allow a
procedure that _receives_ a value in a sense anti-symmetric to the way a
function provides a value.  Thus if one can write
   x + foo(z) + y                  equivalently   x + z.foo + y
to access the value of foo corresponding to z, one should also be able to write
   foo(z) = bar + baz ...          equivalently   z.foo = bar + baz ...
to change it.  (Whether foo is represented by a record field or a procedure is
immaterial).  Then, if one _changes_ the representation of foo, one needn't
change all the references.  One furthermore need not write a silly procedure
   store_foo(instance,value) {instance.foo = value;}
and refer to it by using
   store_foo(z,bar+baz...); /* which argument is the value that gets stored? */
just to plaster over the syntactic differences that would arise if one were
someday to decide to change the representation of foo.

To my knowledge, POP-2 and MESA are the only languages used by more than 20
people that allow this.

It may be useful to keep this idea in mind when pondering the issues of
"state" in functional languages.

Van Snyder

Reply via email to