[no subject]

To: common-lisp@SU-AI.ARPA

From: Kjeld Hvatum <KSH@MIT-MC.ARPA>

Date: Wed, 11 Sep 85 23:34:13 EDT

From: Stephen E. Bacher
To: Common LISP mailing list
Re: Modifying constants in compiled code
From Evan Kirshenbaum:
> (defmacro compute-once (form)
> (let ((cell (cons nil nil)))
> `(if (car ',cell) (cdr ',cell)
> (progn
> (setf (car ',cell) t)
> (setf (cdr ',cell) ,form)))))
>
From Bernard S. Greenberg:
> (defun switch ()
> (let ((y '#.(generate-cellx)))
> (prog1 (car y) (rplaca y t))))
>
> (defun generate-cellx () (cons nil nil))
It seems to me that both of the above examples of self-modifying code
that won't modify "read-only" structures are highly dependent upon the
behavior of the compiler. I generally expect the compiler, when it sees
a form (QUOTE (mumble frotz)), to generate machine code to reference a
LISP structure (mumble frotz) built in an area where constants are
habitually placed, most likely a read-only area (if the implementation
permits it).
So what is the difference between '(nil) and '#.(cons nil nil), if we
assume that what the compiler's call to READ returns is what the
compiler sees?
The same applies to a form to be compiled that is the result of a
macro expansion (as in the macro-expansion-time-let example above).
I can see how this might work if you compile from within the LISP
environment and simply create a pointer to previously built LISP
structure, but when you compile a file things are usually different.
At least in my compiler, which works on files only, this is the case.
(And in fact, if the compiler doesn't collapse EQUAL list structures,
which mine doesn't, the first example doesn't work AT ALL anyway!
But that point has already been brought out, so it needs no further
discussion.)
So wherein lies the "non-read-only-ness" of the thing???