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

Re: Flush COMPILER-LET?



>     (TYPED-VAR Z) won't be expanded until I finally call this closure,
>     but by then the COMPILER-LET bindings have long since gone.
> 
> Only happens in interpreted-only implementations which have no
> semantic pre-pass. Why am I not surprised? Sigh...

I agree with you there (that a pre-pass eliminates the problem).  I'm
not sure why you say "interpreted-only implementations", though.  Lisps
that have a compiler can still have this problem in their interpreter.

>   > You can do the same thing with MACROLET, but it feels quite awkward.
> 
>   But it works. ...
> 
> If you can think of it. I guess I think it's such a radical trick that
> average programmers will never think of.

Well, I had to do something like this recently.  I wrote it with
COMPILER-LET and, since the Lisp I used lacked a pre-pass in its
interpreter, it didn't work.  So I tried MACROLET in various ways.
The COMPILER-LET solution was certainly easier to discover.

> It's yucky because it doesn't let you say what you really mean. You get so 
> caught up in mechanism that you lose the expressional abstraction a variable
> provides. Further, it's harder than this example because of the need to use
> explicit MACROEXPAND and an ENV argument.

That's what I did too (use MACROEXPAND and &ENVIRONMENT).  But I decided
it was too yucky and eventually hit on the following variation:

 (defmacro local-type-declare (declarations &body forms)
   (expand-local-type-declare '() declarations forms))

 (defmacro typed-var (var)
   (error "TYPED-VAR [of ~S] must be in a LOCAL-TYPE-DECLARE." var))

 (defun expand-local-type-declare (nest declarations forms)
   (let ((nested-declarations (append declarations nest)))
     `(macrolet
	  ((local-type-declare (declarations &body forms)
             (expand-local-type-declare 
               ',nested-declarations declarations forms))
           (typed-var (var)
             (let ((type (assoc var ',nested-declarations)))
               (if type `(the ,(cadr type) ,var) var))))
        ,@forms)))

> Assuming COMPILER-LET was made to work reliably (including the situation
> described above) and a reasonable example was provided,

I wouldn't want to flush it if it could be made to work reliably.
But what if it can't?

> Also, the MACROLET version doesn't deal with the issue of side-effects.
> Offhand I see no way to use MACROLET to simulate a situation which uses
> COMPILER-LET and where a compiler-let variable is re-assigned (by SETQ)
> in a contained macro call. The kind of macro where you'd do that would be 
> 
>  (WITH-MY-STICKY-DECLARATIONS
>    (+ (MY-THE FIXNUM X) (MY-SQRT X)))
> 
> where MY-THE might be like THE, but it could push onto a list of
> declarations maintained by WITH-MY-STICKY-DECLARATIONS so that MY-SQRT
> could be a macro that knew X was a FIXNUM.

Would something like the following suffice?

 (defmacro with-my-sticky-declarations (&body forms)
   (let ((place (gensym)))
     `(macrolet
	  ((my-the (type var)
	     (push (list var type) ,place)
	     `(the ,type ,var))
	   (my-sqrt (form)
	     (if (symbolp form)
		 (let ((type (assoc form ,place)))
		   ...)
	       ...)))
	,@forms)))

-- Jeff