[comp.lang.lisp] Read macro behavior

eliot@phoenix.Princeton.EDU (Eliot Handelman) (12/23/89)

Here's a little problem:



(set-macro-character #\$ #'(lambda (stream char)
			     (declare (ignore char))
			     (get (read stream t nil t) 'foo)))

;;; S is a structure printed as #<S>

(setf (get :blah 'foo) (make-s))

$:blah

;; In Lucid 2.0 and Kcl: 

==> #<S>

;; in Franz (on the NeXT):

==> error, because it tries to eval #<S>.

It appears that Franz is passing on the results of the readmacro to eval,
whereas Lucid and KCl aren't. Franz says they're right, what accounts for
the disparate behavior then?

--eliot

barmar@Think.COM (12/23/89)

In article <12384@phoenix.Princeton.EDU> eliot@phoenix.Princeton.EDU (Eliot Handelman) writes:
>It appears that Franz is passing on the results of the readmacro to eval,
>whereas Lucid and KCl aren't. Franz says they're right, what accounts for
>the disparate behavior then?

In both cases the result of the readmacro is passed to EVAL, since you
were typing to the read-eval-print loop, which passes whatever you type to
EVAL.  To see that this is true, try

(setf (get :bar 'foo) '(+ 1 2))
$:bar
==> 3
'$:bar
==> (+ 1 2)

The difference is that different Lisps have different behavior when
evaluating a structure.  CLtL doesn't specify the behavior when evaluating
structures (see p.54 -- structures aren't "valid forms", so evaluating them
"is an error"), so the result is implementation-dependent.  Lucid and KCL
have extended the evaluator to treat structures as self-evaluating forms,
while Franz has defined it to signal an error.  They are both in
conformance; your use is not portable (it will be in ANSI CL -- X3J13 has
decided to specify that all data types other than lists and symbols are
self-evaluating).

You can get what you probably want in a portable way with the following
version of your read-macro:

(set-macro-character #\$ #'(lambda (stream char)
			     (declare (ignore char))
			     `(quote ,(get (read stream t nil t) 'foo))))

Of course, this is only useful if you will always be executing the result
of a $ form.  If $:blah were typed in response to a (read) in your program,
the result would include the quote, which you would have to strip out.  A
better solution would be to use your original macro, but remember to write
'$:blah in evaluation contexts.
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar