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

Constant Smashing

>From:	IN%"NGALL@G.BBN.COM" 14-JUN-1988 03:53
>Subj:	Re: constant folding/smashing
>    Date: Fri, 10 Jun 88 11:32 EDT
>    From: ELIOT@cs.umass.edu
>	What about constant hash-tables?  No variety of QUOTE can build
>	a constant hash table because there is no notation for them.
>	(I don't count #.(make-hash-table...) because it's so gross.)
>Once again, I will state that the problem is not notation.  QUOTE
>cannot cons its argument into RO-space because the argument has ALREADY
>BEEN CONSED.  All QUOTE can do it to cons in RO-space an EQUAL COPY of
>its argument and return that copy.  But there is NO SUCH THING as an
>EQUAL "COPY" of a hashtable.  It doesn't matter that its gross, it
>just won't work.

Further supporting the idea that a general mechanism apart from QUOTE
is required to properly support read-only data structures, if read
only data becomes a Common Lisp concept.

>	In general I like the idea of quoted constants being read-only,
>	because it ensures that the semantics of a function at run-time
>	are apparent from its textual representation as code.  If constants
>	are not read-only then:
>	(defun foo ()
>	    '(a b c))
>	Really means
>	(defun foo ()
>	    G00047)
>	(setq G00047 '(a b c))
>Funny, this is the semantics that most Lisper's have as their initial
>mental model (and I assume find the most intuitive).  

I'm not sure the code expresses my point clearly.  Functions that return
quoted constants are subject to *external* modification of their *internal*
behavior.  Its likely that you can get accidentally self modifying code.
I've seen this cause obscure bugs.  I don't think it is intuitive.
The source code for the first definition of FOO makes it notationally
"obvious" (incorrectly) that FOO always returns the list (A B C).
The source code for the second definition makes it notationally clear
that there is some global and mutable state involved.

>It is also the
>semantics of all (?) CL interpreters.  QUOTE MUST have the same
>behavior in the compiler and the interpreter.  To do otherwise is to
>introduce a compiler/interpreter incompatibility as confusing and
>error-prone as the SPECIAL variable incompatibility used to be.  Agreed?

No.  QUOTE must have the same *semantics* in the compiler and interpreter.
However, there may be aspects of the semantics that are not fully
defined and an implementation may have differences in those areas.
(The binding environment of a variable is deemed much too important
to leave unspecified.)   It would be coherent to specify that it is
"an error" to modify a quoted constant without requiring an implementation
to ever detect it.  A legitimate implementation might detect it some
of the time (on tuesdays and thursdays perhaps) but not at other times.

In the case of QUOTE some errors might go undetected.  This is not good,
but it is not as dangerous a flaw as the SPECIAL variable problem,
which is characterized by different compiled/interpreted behavior
where neither behavior draws attention to the actual source of the
problem.  It is relatively straightforward to debug a problem that
causes the debugger to freeze execution near the actual cause.

To support this argument I must make one more claim.  I must claim that
compiling a function produces a *new* function definition that is
semantically equivalent to the old one, but it does not have to
be composed of the 'same' forms.  This is because of the definition of
CONSTANTP on p.324 (CLtL) which (in my reading) implies (eq (foo) (foo))
when FOO is defined as above.  [Because of (constantp (quote a b c))]

	(eq (foo) (foo)) => T
	(setq x (foo))
	(compile 'foo)
	(eq x (foo)) => Ambiguous
	(eq (foo) (foo)) => T

And no identity holds accross the act of compilation.

>If you want to suggest that the interpreter should be changed to make
>QUOTE return a RO-EQUAL-copy of its arg when possible*** (as I think JonL
>may have been suggesting?), then consider what a pain it will cause at
>the top-level:
>> (setf foo '(1 2 3))
>(1 2 3)
>> (push 0 foo)
>>>>>> Error ...

Tsk, Tsk.  THAT won't cause an error.  You meant: (setf (car foo) 'one)?

An implementation can go either way on this.  Experience with several
different implementations may show what the happy compromise is.
Actually I think that QUOTE should produce read only data structures
and BACKQUOTE should create newly CONSed mutable data structures.

>Instead, you'll have to do:
>> (setf foo (list 1 2 3))

Or use backquote.

>(1 2 3)
>> (push 0 foo)
>(0 1 2 3)
>A lot of Lisp textbooks will have to be rewritten!
>-- Nick
>*** Actually, the interpreter's handling of self-evaluating forms will
>have to be changed too.

If you agree with what I said about *external* modification of
*internal* behavior then it would have to apply to strings, characters
etc. also.  But the added complexity is negligable, since "Foo"
or #\Foo could be treated as (quote "Foo") or (quote #\Foo).