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


    Date: Mon, 7 Jul 86 15:13 EDT
    From: Jonathan A Rees <JAR@MIT-AI.ARPA>

    COMPILER-LET seems pretty confused; CLtL says that it is intended
    "for communication among complicated macros," but as far as I can tell
    it doesn't reliably serve this end, since its effect is not the same in
    interpreted and compiled code.  Consider the following example:

	(defvar *foo* nil)
	(defmacro foo () `',*foo*)
	(defun test ()
	  (compiler-let ((*foo* t))
	    #'(lambda () (foo))))

    Now if TEST is "interpreted," then (funcall (test)) presumably returns
    NIL; if it's "compiled," then (funcall (test)) presumably returns T.

It always returns T in the implementation on my machine.

But I see your point.  If the macro foo was not expanded until after the
closure was made, and if the interpreter failed to include the COMPILER-LET
information in the closure, it would return NIL.

This is item #300 (or thereabouts) among the minor design decisions that
were not reevaluated when full lexical scoping was added to the language
late in the process of designing Common Lisp.  Perhaps there should be a
committee of interested persons to search for these systematically.  To
get you started, #259 is: what does this form do?
  (dotimes (i n) (push #'(lambda () i) l))

I don't know why you say COMPILER-LET is difficult to handle in code-walkers.
I think it might be the second-easiest special form, after QUOTE.  You just
bind the special variables and proceed.

    Is there any kind of thing which can be done using COMPILER-LET which
    can't be done using MACROLET?

MACROLETs aren't visible in the scope of the body of a macro expansion
function.  That's the whole reason why COMPILER-LET uses dynamic
scoping.  I thought about this a bit and looked at some real examples,
too large and unilluminating to include here.  I think the answer is
that since COMPILER-LET can only affect the expansion of macros, it can
always be replaced with a MACROLET that redefines the macro to a new
version of its body with the COMPILER-LET variable's value included in
the macro as a constant.  This gets cumbersome when the macro definition
is large (this can be addressed by calling a subroutine) or when there
are nested COMPILER-LETs for different variables or variables that are
not constant but depend on the particular macro call (I haven't figured
out how to cope with that, other than by using the trick of explicitly
calling MACROEXPAND that you had in your mail, which is essentially using
the MACROLET environment to simulate deep-bound special variables).

Another reason for COMPILER-LET, no doubt bogus, can be found in the
Lisp Machine manual ("Chine Nual").  It can be used to bind switches
that affect the operation of the compiler.  Presumably this could be
done with declarations or special forms, at some small increase in
compiler complexity.  Except for this application, COMPILER-LET doesn't
appear to have anything to do specifically with compilers, and is
evidently misnamed.