[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
-------