[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: issue COMPILER-LET-CONFUSION
- To: Kent M Pitman <KMP@STONY-BROOK.SCRC.Symbolics.COM>
- Subject: Re: issue COMPILER-LET-CONFUSION
- From: sandra%defun@cs.utah.edu (Sandra J Loosemore)
- Date: Thu, 16 Feb 89 15:35:37 MST
- Cc: sandra%defun@cs.utah.edu, CL-Compiler@SAIL.Stanford.EDU, iim@ECLA.USC.EDU
- In-reply-to: Kent M Pitman <KMP@STONY-BROOK.SCRC.Symbolics.COM>, Thu, 16 Feb 89 16:26 EST
Looking at what happens to the LOCAL-TYPE-DECLARE/TYPED-VAR example
we've been using may help clarify things. Since you initially
suggested this example as being a prototypical use of COMPILER-LET, I
would think that most of what I've done with it would apply equally
well to other uses.
Your implementation using COMPILER-LET was:
(defvar *local-type-declarations* '())
(defmacro local-type-declare (declarations &body forms)
`(compiler-let ((*local-type-declarations*
(append ',declarations *local-type-declarations*)))
,@forms))
(defmacro typed-var (var)
(let ((type (assoc var *local-type-declarations*)))
(if type `(the ,(cadr type) ,var) var)))
This could be implemented using SYMBOL-MACROLET like:
(let ((temp (gensym)))
(defmacro local-type-declare (declarations &body forms &environment env)
`(symbol-macrolet ((,temp ,(append declarations
(symbol-macro-value temp env))))
,@forms))
(defmacro typed-var (var &environment env)
(let ((type (assoc var (symbol-macro-value temp env))))
(if type `(the ,(cadr type) ,var) var)))
)
(defun symbol-macro-value (symbol env &optional default)
(multiple-value-bind (expansion macro-p) (macroexpand-1 symbol env)
(if macro-p expansion default)))
Now to answer your specific questions.
> How will the lookup routine be able to take [the name of the symbol]
> as an argument and figure out what the gensym was called?
Here, I've made it a lexical variable. Both macros have a handle on
it and nobody else can possibly be using that symbol. I could have
made it a special or a DEFCONSTANT instead.
> If there's a place to store that relation,
> why not just store the relation between [the symbol] and the value itself
> rather than indirecting through an irrelevant macroexpand?
Because the macroexpand guarantees that you'll get the right value for
the -lexical- scope in which the macro -call- appears. (Not the
dynamic scope of the call, or the lexical scope of its definition, or
any of the other possible permutations.) The macroexpand is
definitely not "irrelevant"; it's at the very core of the technique.
> Also, somewhat unrelated but I just thought of it, the body of
> SYMBOL-MACROLET is not (necessarily) executed at binding time,
> while*COMPILER-LET*'s body is. I'm not sure how that will affect
> things. I can't convince myself that delaying the evaluation of
> that form will have the right effect. [Even if it did, you'd need
> to do (EVAL (MACROEXPAND ...)), not just (MACROEXPAND ...) in
> the lookup routine unless you made the simplification I alluded
> to in the previous paragraph.]
It took me a minute to figure out what you might be referring to here;
do you mean that the -value- (not body) of the symbol macro is a
literal constant? I took care of that by having the macro that
produces the SYMBOL-MACROLET do the evaluation. Look closely at the
backquoted expression in the two versions of LOCAL-TYPE-DECLARE. Note
that the COMPILER-LET version could also have done the APPEND at
macroexpand time instead of including it in the macroexpansion.
Are you still confused?
-Sandra
-------