[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Issue: CONSTANT-SIDE-EFFECTS (no proposal)

> I would very much like to know what implementations do something akin to 
> the PDP10 MacLisp treatment of "constants", or maybe an extension thereto:
>   (1) except possibly for symbols, they are stored in a separate storage 
>       area, which will be made write-protected at the next "disksave";

The TI and LMI implementations put constants that are referenced by
compiled functions into a write-protected memory area at the time a
compiled object file is loaded.  This is not done for constants in
top-level forms such as DEFVAR.

> Lucid also treats many "compiled-functions" as constants (i.e. "read-only"),

TI and LMI do also, but this doesn't seem relevant since there is no
standard way to reach inside a COMPILED-FUNCTION object.

> Additionally, before investing any time in such a proposal, I wonder how 
> controversial it would be to insist (or, maybe just "suggest") that the 
> interpreter evaluate (QUOTE <anything>) not merely into <anything>, but 
> rather into a possibly-cached copy of <anything> that is known to be 
> CONSTANT-STORAGE-P.  That is, the interpreter must do something very similar
> to what the compiler does for constants.  Without this clause -- without
> rectifying the Lisp 1.5 mistake that defines QUOTE like CAR -- there is
> far too much potential for interpreted/compiled mismatch.  I really 
> wouldn't want to address "constants" if it applied _only_ to the output
> of the compiler.

A couple of years ago I tried to have in-memory compilation write-protect
constants so that it would be consistent with code loaded from a compiled
file.  I eventually gave up because it proved too difficult to avoid
protecting things that users didn't expect to be protected and to avoid
problems with copying shared or recursive data structures.  Note that the
object file loader knows that a value is only used as a constant before it
creates it, so it can create it in the proper memory area, but READ does
not have any such context information, so write-protecting constants in
the interpreter or in-memory compilation means copying them.

Note that while it seems to be agreed that it is wrong to do

  (DEFUN FX () '(A B C))

it is common practice to do things like

  (DEFVAR *X* '(A B C))
  (SETF (SECOND *X*) 'Z)

Perhaps it would be better to say (DEFVAR *X* (COPY-LIST '(A B C))) but
requiring that would invalidate a lot of existing code.  I don't think
that this inconsistency is really a problem because the main reason for
prohibiting alteration of constants in functions is that it (usually
unexpectedly) causes the function to be different the next time it is
called, but a particular instance of a top-level DEFVAR can only be
executed once.  The other reason, sharing of EQUAL constants, is also of
less interest for top-level forms than in functions.

In other words, I don't think an ideal solution is possible, but a
reasonable and useful solution is.