396 lines
26 KiB
HTML
396 lines
26 KiB
HTML
<!-- Common Lisp HyperSpec (TM), version 7.0 generated by Kent M. Pitman on Mon, 11-Apr-2005 2:31am EDT -->
|
|
<HTML>
|
|
<HEAD>
|
|
<TITLE>CLHS: Issue COMPILER-LET-CONFUSION Writeup</TITLE>
|
|
<LINK HREF="../Data/clhs.css" REL="stylesheet" TYPE="text/css" />
|
|
<META HTTP-EQUIV="Author" CONTENT="Kent M. Pitman">
|
|
<META HTTP-EQUIV="Organization" CONTENT="LispWorks Ltd.">
|
|
<LINK REL=TOP HREF="../Front/index.htm">
|
|
<LINK REL=COPYRIGHT HREF="../Front/Help.htm#Legal">
|
|
<LINK REL=DISCLAIMER HREF="../Front/Help.htm#Disclaimer">
|
|
<LINK REL=PREV HREF="../Issues/iss065_w.htm">
|
|
<LINK REL=UP HREF="../Issues/iss066.htm">
|
|
<LINK REL=NEXT HREF="../Issues/iss067_w.htm">
|
|
</HEAD>
|
|
<BODY>
|
|
<H1><A REV=MADE HREF="http://www.lispworks.com/"><IMG WIDTH=80 HEIGHT=65 ALT="[LISPWORKS]" SRC="../Graphics/LWSmall.gif" ALIGN=Bottom></A><A REL=TOP HREF="../Front/index.htm"><IMG WIDTH=237 HEIGHT=65 ALT="[Common Lisp HyperSpec (TM)]" SRC="../Graphics/CLHS_Sm.gif" ALIGN=Bottom></A> <A REL=PREV HREF="../Issues/iss065_w.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Previous]" SRC="../Graphics/Prev.gif" ALIGN=Bottom></A><A REL=UP HREF="../Issues/iss066.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Up]" SRC="../Graphics/Up.gif" ALIGN=Bottom></A><A REL=NEXT HREF="../Issues/iss067_w.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Next]" SRC="../Graphics/Next.gif" ALIGN=Bottom></A></H1>
|
|
|
|
<HR>
|
|
|
|
|
|
|
|
<H2>Issue COMPILER-LET-CONFUSION Writeup</H2>
|
|
|
|
<PRE><B>Issue:</B> <A HREF="iss066.htm">COMPILER-LET-CONFUSION</A><P>
|
|
<B>Forum:</B> Compiler<P>
|
|
<B>References:</B> CLtL p. 112<P>
|
|
Issue DEFINE-OPTIMIZER<P>
|
|
<B>Category:</B> CHANGE<P>
|
|
<B>Edit History:</B> V1, 27 Sep 1988, Sandra Loosemore (initial version)<P>
|
|
V2, 04 Oct 1988, Sandra Loosemore (add another example)<P>
|
|
V3, 31 Oct 1988, Sandra Loosemore (only proposal ELIMINATE)<P>
|
|
V4, 08 Jan 1989, Kent M. Pitman (new alternative)<P>
|
|
V5, 09 Jan 1989, Sandra Loosemore (discussion)<P>
|
|
V6, 08 Mar 1989, Sandra Loosemore (general updating)<P>
|
|
V7, 13 Mar 1989, Sandra Loosemore (fix bug from V6)<P>
|
|
V8, 23 Mar 1989, Sandra Loosemore (fix another bug, add<P>
|
|
to discussion)<P>
|
|
<B>Status:</B> Proposal ELIMINATE passed March 89.<P>
|
|
<P>
|
|
<B>Problem Description:<P>
|
|
</B><P>
|
|
The description of the COMPILER-LET special form in CLtL is confusing<P>
|
|
to many people. There are no examples provided to make it clear how it<P>
|
|
is supposed to be used. The only description which is offered is overly<P>
|
|
concrete, which has led to confusion about the intent of COMPILER-LET,<P>
|
|
and about its implementability.<P>
|
|
<P>
|
|
The intent of COMPILER-LET was to permit information to be communicated<P>
|
|
between macros by use of dynamic variables at macroexpansion time.<P>
|
|
It was not necessary to the intended uses of COMPILER-LET that such<P>
|
|
variables ever be bound at execution time. <P>
|
|
<P>
|
|
Unfortunately, probably because some implementations did not primitively<P>
|
|
support COMPILER-LET at the time CLtL was written, an exception was <P>
|
|
permitted to make COMPILER-LET `more or less work' in interpreters: <P>
|
|
the COMPILER-LET variables were permitted to be bound at execution time.<P>
|
|
The problem was further compounded by the fact that CLtL presented this<P>
|
|
exception as part of COMPILER-LET's contract rather than as an <P>
|
|
implementation note, and by the fact that no examples of actually using<P>
|
|
COMPILER-LET correctly are provided.<P>
|
|
<P>
|
|
One particular case where problems have resulted is a situation like<P>
|
|
(compiler-let ((*v* 1))<P>
|
|
#'(<A REL=DEFINITION HREF="../Body/a_lambda.htm#lambda"><B>lambda</B></A> () (m)))<P>
|
|
where M is a macro that refers to *V*. In some implementations, M is<P>
|
|
not macroexpanded until the dynamic extent of the *V* binding has<P>
|
|
ended.<P>
|
|
<P>
|
|
Subtle bugs can be introduced because of the different handling of the<P>
|
|
variable bindings in the interpreter and the compiler. In compiled<P>
|
|
code, the bindings are only lexically visible during the expansion of<P>
|
|
macros at compile time, while in interpreted code the bindings have<P>
|
|
dynamic scope and may also be seen during ordinary evaluation if<P>
|
|
evaluation and macroexpansion happen "in parallel".<P>
|
|
<P>
|
|
Further compatibility problems can result from the value forms being<P>
|
|
evaluated in a null lexical environment in the compiler and the ordinary<P>
|
|
lexical environment in the interpreter.<P>
|
|
<P>
|
|
<B>Background and Analysis:<P>
|
|
</B><P>
|
|
It should be clear up front that COMPILER-LET is not computationally<P>
|
|
essential. Most (if not all) uses of it can be rewritten using <A REL=DEFINITION HREF="../Body/s_flet_.htm#macrolet"><B>MACROLET</B></A><P>
|
|
or <A REL=DEFINITION HREF="../Body/s_symbol.htm#symbol-macrolet"><B>SYMBOL-MACROLET</B></A>.<P>
|
|
<P>
|
|
A typical use of COMPILER-LET might be:<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/m_defpar.htm#defvar"><B>defvar</B></A> *local-type-declarations* '())<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/m_defmac.htm#defmacro"><B>defmacro</B></A> local-type-declare (declarations <A REL=DEFINITION HREF="../Body/03_dd.htm#AMbody"><B>&body</B></A> forms)<P>
|
|
`(compiler-let ((*local-type-declarations* <P>
|
|
(<A REL=DEFINITION HREF="../Body/f_append.htm#append"><B>append</B></A> ',declarations *local-type-declarations*)))<P>
|
|
,@forms))<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/m_defmac.htm#defmacro"><B>defmacro</B></A> typed-var (var)<P>
|
|
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>let</B></A> ((<A REL=DEFINITION HREF="../Body/a_type.htm#type"><B>type</B></A> (<A REL=DEFINITION HREF="../Body/f_assocc.htm#assoc"><B>assoc</B></A> var *local-type-declarations*)))<P>
|
|
(<A REL=DEFINITION HREF="../Body/s_if.htm#if"><B>if</B></A> <A REL=DEFINITION HREF="../Body/a_type.htm#type"><B>type</B></A> `(<A REL=DEFINITION HREF="../Body/s_the.htm#the"><B>the</B></A> ,(<A REL=DEFINITION HREF="../Body/f_car_c.htm#cadr"><B>cadr</B></A> <A REL=DEFINITION HREF="../Body/a_type.htm#type"><B>type</B></A>) ,var) var)))<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>defun</B></A> f (x y)<P>
|
|
(local-type-declare ((x <A REL=DEFINITION HREF="../Body/t_fixnum.htm#fixnum"><B>fixnum</B></A>) (y <A REL=DEFINITION HREF="../Body/a_float.htm#float"><B>float</B></A>))<P>
|
|
(+ (typed-var x) (typed-var y))))<P>
|
|
<P>
|
|
<P>
|
|
The same thing could be accomplished using MACROLET:<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/m_defmac.htm#defmacro"><B>defmacro</B></A> local-type-declare (declarations <A REL=DEFINITION HREF="../Body/03_dd.htm#AMbody"><B>&body</B></A> forms)<P>
|
|
(local-type-declare-aux declarations forms))<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/m_defmac.htm#defmacro"><B>defmacro</B></A> typed-var (var) var)<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/s_eval_w.htm#eval-when"><B>eval-when</B></A> (<A REL=DEFINITION HREF="../Body/f_eval.htm#eval"><B>eval</B></A> <A REL=DEFINITION HREF="../Body/f_cmp.htm#compile"><B>compile</B></A> <A REL=DEFINITION HREF="../Body/f_load.htm#load"><B>load</B></A>)<P>
|
|
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>defun</B></A> local-type-declare-aux (declarations forms)<P>
|
|
`(<A REL=DEFINITION HREF="../Body/s_flet_.htm#macrolet"><B>macrolet</B></A> ((typed-var (var)<P>
|
|
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>let</B></A> ((<A REL=DEFINITION HREF="../Body/a_type.htm#type"><B>type</B></A> (<A REL=DEFINITION HREF="../Body/f_assocc.htm#assoc"><B>assoc</B></A> var ',declarations)))<P>
|
|
(<A REL=DEFINITION HREF="../Body/s_if.htm#if"><B>if</B></A> <A REL=DEFINITION HREF="../Body/a_type.htm#type"><B>type</B></A> `(<A REL=DEFINITION HREF="../Body/s_the.htm#the"><B>the</B></A> ,(<A REL=DEFINITION HREF="../Body/f_car_c.htm#cadr"><B>cadr</B></A> <A REL=DEFINITION HREF="../Body/a_type.htm#type"><B>type</B></A>) ,var) var)))<P>
|
|
(local-type-declare (new-declarations <A REL=DEFINITION HREF="../Body/03_dd.htm#AMbody"><B>&body</B></A> new-forms)<P>
|
|
(local-type-declare-aux<P>
|
|
(<A REL=DEFINITION HREF="../Body/f_append.htm#append"><B>append</B></A> new-declarations ',declarations)<P>
|
|
new-forms)))<P>
|
|
,@forms)))<P>
|
|
<P>
|
|
<P>
|
|
A further alternative would be to use <A REL=DEFINITION HREF="../Body/s_symbol.htm#symbol-macrolet"><B>SYMBOL-MACROLET</B></A> (this particular<P>
|
|
implementation assumes that issue <A HREF="iss104.htm">DEFINING-MACROS-NON-TOP-LEVEL</A> passes):<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>let</B></A> ((temp (<A REL=DEFINITION HREF="../Body/f_gensym.htm#gensym"><B>gensym</B></A>)))<P>
|
|
(<A REL=DEFINITION HREF="../Body/m_defmac.htm#defmacro"><B>defmacro</B></A> local-type-declare (declarations <A REL=DEFINITION HREF="../Body/03_dd.htm#AMbody"><B>&body</B></A> forms <A REL=DEFINITION HREF="../Body/03_dd.htm#AMenvironment"><B>&environment</B></A> env)<P>
|
|
`(<A REL=DEFINITION HREF="../Body/s_symbol.htm#symbol-macrolet"><B>symbol-macrolet</B></A> ((,temp ',(<A REL=DEFINITION HREF="../Body/f_append.htm#append"><B>append</B></A> declarations<P>
|
|
(symbol-macro-value temp env))))<P>
|
|
,@forms))<P>
|
|
(<A REL=DEFINITION HREF="../Body/m_defmac.htm#defmacro"><B>defmacro</B></A> typed-var (var <A REL=DEFINITION HREF="../Body/03_dd.htm#AMenvironment"><B>&environment</B></A> env)<P>
|
|
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>let</B></A> ((<A REL=DEFINITION HREF="../Body/a_type.htm#type"><B>type</B></A> (<A REL=DEFINITION HREF="../Body/f_assocc.htm#assoc"><B>assoc</B></A> var (symbol-macro-value temp env))))<P>
|
|
(<A REL=DEFINITION HREF="../Body/s_if.htm#if"><B>if</B></A> <A REL=DEFINITION HREF="../Body/a_type.htm#type"><B>type</B></A> `(<A REL=DEFINITION HREF="../Body/s_the.htm#the"><B>the</B></A> ,(<A REL=DEFINITION HREF="../Body/f_car_c.htm#cadr"><B>cadr</B></A> <A REL=DEFINITION HREF="../Body/a_type.htm#type"><B>type</B></A>) ,var) var)))<P>
|
|
)<P>
|
|
<P>
|
|
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>defun</B></A> symbol-macro-value (<A REL=DEFINITION HREF="../Body/t_symbol.htm#symbol"><B>symbol</B></A> env <A REL=DEFINITION HREF="../Body/03_da.htm#AMoptional"><B>&optional</B></A> default)<P>
|
|
(<A REL=DEFINITION HREF="../Body/m_multip.htm#multiple-value-bind"><B>multiple-value-bind</B></A> (expansion macro-p) (<A REL=DEFINITION HREF="../Body/f_mexp_.htm#macroexpand"><B>macroexpand</B></A> <A REL=DEFINITION HREF="../Body/t_symbol.htm#symbol"><B>symbol</B></A> env)<P>
|
|
(<A REL=DEFINITION HREF="../Body/s_if.htm#if"><B>if</B></A> macro-p (<A REL=DEFINITION HREF="../Body/f_eval.htm#eval"><B>eval</B></A> expansion) default)))<P>
|
|
<P>
|
|
<P>
|
|
Opinion is divided as to which is more understandable. Some<P>
|
|
people find the COMPILER-LET idiom more understandable (assuming that<P>
|
|
it can be made to work consistently in compiled and interpreted<P>
|
|
code), while others find it just as natural to use <A REL=DEFINITION HREF="../Body/s_flet_.htm#macrolet"><B>MACROLET</B></A> or <P>
|
|
<A REL=DEFINITION HREF="../Body/s_symbol.htm#symbol-macrolet"><B>SYMBOL-MACROLET</B></A>.<P>
|
|
<P>
|
|
The issues are these:<P>
|
|
<P>
|
|
- Is it possible to implement COMPILER-LET in a usefully consistent<P>
|
|
way in all implementations?<P>
|
|
<P>
|
|
- Are the benefits of providing a useful and compatible implementation<P>
|
|
of COMPILER-LET worth any associated cost?<P>
|
|
<P>
|
|
Two proposals are presented below:<P>
|
|
<P>
|
|
- Option REPAIR argues that COMPILER-LET provides interesting<P>
|
|
functionality that can be implemented in a manner that is usefully<P>
|
|
consistent across implementations, and that the associated cost<P>
|
|
is low enough for it to be worthwhile to do so.<P>
|
|
<P>
|
|
- Option ELIMINATE argues that COMPILER-LET complicates the language<P>
|
|
and that providing this construct is not worth the associated <P>
|
|
implementation cost.<P>
|
|
<P>
|
|
<P>
|
|
<B>Proposal (COMPILER-LET-CONFUSION:REPAIR):<P>
|
|
</B><P>
|
|
Strike the existing definition of COMPILER-LET. Redefine it as follows:<P>
|
|
<P>
|
|
COMPILER-LET [Special form]<P>
|
|
<P>
|
|
COMPILER-LET is similar to <A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A>, but it always makes special <P>
|
|
bindings and makes those bindings visible only during <P>
|
|
macroexpansion of forms in the body, not during the runtime<P>
|
|
execution of those forms. <P>
|
|
<P>
|
|
If proposal DEFINE-OPTIMIZER:NEW-FACILITY is accepted, then<P>
|
|
optimizer functions are also executed in a dynamic environment<P>
|
|
in which COMPILER-LET bindings are visible.<P>
|
|
<P>
|
|
The intent is that some macros might <A REL=DEFINITION HREF="../Body/f_mexp_.htm#macroexpand"><B>macroexpand</B></A> into calls to<P>
|
|
COMPILER-LET in which the body would the contain references to<P>
|
|
macros which access the variables in the COMPILER-LET.<P>
|
|
<P>
|
|
The initial value forms of the bindings, if any, are always <P>
|
|
evaluated in a null lexical context, regardless of whether the<P>
|
|
COMPILER-LET expression is being interpreted or compiled.<P>
|
|
<P>
|
|
The initial value forms of the bindings, if any, are evaluated in<P>
|
|
a dynamic context where the bindings of any lexically enclosing<P>
|
|
COMPILER-LET are visible, and where dynamic execution-time <P>
|
|
environment may or may not be visible.<P>
|
|
<P>
|
|
Implementation Note: Permitting the execution-time dynamic<P>
|
|
environment to be visible when initializing COMPILER-LET variables<P>
|
|
is a concession to some interpreters which may have to do this in<P>
|
|
order to keep the cost down. Where feasible, implementors should<P>
|
|
try not to make the runtime environment visible.<P>
|
|
<P>
|
|
Rationale:<P>
|
|
<P>
|
|
This gives a consistent description of COMPILER-LET which separates<P>
|
|
issues of intent from those of implementation in a way that makes it<P>
|
|
possible for portable code to make serious use of it, and which does<P>
|
|
not force gratuitous incompatibilities between interpreters and<P>
|
|
compilers.<P>
|
|
<P>
|
|
This description of COMPILER-LET can be implemented without undue<P>
|
|
cost by all implementations. See "Cost to Implementors" for details.<P>
|
|
<P>
|
|
Cost to Implementors:<P>
|
|
<P>
|
|
Modest, but nontrivial in some implementations.<P>
|
|
<P>
|
|
In compiled code, and in interpreters doing a one-time semantic<P>
|
|
prepass, it should be fairly easy for COMPILER-LET to cause the <P>
|
|
variables to get bound (using <A REL=DEFINITION HREF="../Body/s_progv.htm#progv"><B>PROGV</B></A>) during semantic analysis.<P>
|
|
<P>
|
|
In interpreters which do not do a semantic-prepass, it is necessary<P>
|
|
to fully <A REL=DEFINITION HREF="../Body/f_mexp_.htm#macroexpand"><B>macroexpand</B></A> the body. Assuming the presence of a<P>
|
|
SYSTEM::MACROEXPAND-ALL primitive, the definition of COMPILER-LET<P>
|
|
could look like:<P>
|
|
(<A REL=DEFINITION HREF="../Body/m_defmac.htm#defmacro"><B>DEFMACRO</B></A> COMPILER-LET (BINDINGS <A REL=DEFINITION HREF="../Body/03_dd.htm#AMbody"><B>&BODY</B></A> FORMS <A REL=DEFINITION HREF="../Body/03_dd.htm#AMenvironment"><B>&ENVIRONMENT</B></A> ENV)<P>
|
|
(<A REL=DEFINITION HREF="../Body/s_setq.htm#setq"><B>SETQ</B></A> BINDINGS ;; Assure no non-atom bindings<P>
|
|
(<A REL=DEFINITION HREF="../Body/f_mapc_.htm#mapcar"><B>MAPCAR</B></A> #'(<A REL=DEFINITION HREF="../Body/a_lambda.htm#lambda"><B>LAMBDA</B></A> (BINDING) <P>
|
|
(<A REL=DEFINITION HREF="../Body/s_if.htm#if"><B>IF</B></A> (<A REL=DEFINITION HREF="../Body/a_atom.htm#atom"><B>ATOM</B></A> BINDING) (<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>LIST</B></A> BINDING) BINDING))<P>
|
|
BINDINGS))<P>
|
|
(<A REL=DEFINITION HREF="../Body/s_progv.htm#progv"><B>PROGV</B></A> (<A REL=DEFINITION HREF="../Body/f_mapc_.htm#mapcar"><B>MAPCAR</B></A> #'<A REL=DEFINITION HREF="../Body/f_car_c.htm#car"><B>CAR</B></A> BINDINGS)<P>
|
|
(<A REL=DEFINITION HREF="../Body/f_mapc_.htm#mapcar"><B>MAPCAR</B></A> #'(<A REL=DEFINITION HREF="../Body/a_lambda.htm#lambda"><B>LAMBDA</B></A> (BINDING) (<A REL=DEFINITION HREF="../Body/f_eval.htm#eval"><B>EVAL</B></A> (<A REL=DEFINITION HREF="../Body/f_car_c.htm#cadr"><B>CADR</B></A> BINDING))) BINDINGS)<P>
|
|
(SYSTEM::MACROEXPAND-ALL `(<A REL=DEFINITION HREF="../Body/s_progn.htm#progn"><B>PROGN</B></A> ,@FORMS) ENV)))<P>
|
|
This reduces the problem of writing a program capable of doing a<P>
|
|
full macroexpansion. Many systems already have such a facility.<P>
|
|
Pitman wrote such a facility in Cloe Runtime in order support <P>
|
|
<A REL=DEFINITION HREF="../Body/s_symbol.htm#symbol-macrolet"><B>SYMBOL-MACROLET</B></A> (before it was christened a special form); it was<P>
|
|
about 750 lines of relatively straightforward, well-commented code.<P>
|
|
<P>
|
|
Cost to Users:<P>
|
|
<P>
|
|
Code currently depending on this feature is either non-existent or<P>
|
|
already not portable (due to wide variation in implementation <P>
|
|
strategy for COMPILER-LET).<P>
|
|
<P>
|
|
Most users will probably be happy for any interpretation which offers<P>
|
|
them a future shot at portability.<P>
|
|
<P>
|
|
Some users have indicated they dislike interpreters which do a semantic<P>
|
|
prepass, because they like to be able to dynamically redefine macros<P>
|
|
while debugging.<P>
|
|
<P>
|
|
<P>
|
|
<B>Proposal (COMPILER-LET-CONFUSION:ELIMINATE):<P>
|
|
</B><P>
|
|
Remove COMPILER-LET from the language.<P>
|
|
<P>
|
|
Rationale:<P>
|
|
<P>
|
|
Some people think that having one less special form would simplify the<P>
|
|
language. The revised COMPILER-LET semantics, which <A REL=DEFINITION HREF="../Body/f_provid.htm#require"><B>require</B></A><P>
|
|
COMPILER-LET to make special bindings which are only visible during<P>
|
|
expansion of macros which appear lexically within its body, are<P>
|
|
not shared by any other feature in the language, and <A REL=DEFINITION HREF="../Body/f_provid.htm#require"><B>require</B></A> a<P>
|
|
fairly complex implementation technique. There are other<P>
|
|
constructs which are strictly lexical that can be readily used<P>
|
|
to solve the same kinds of problems that COMPILER-LET is intended to<P>
|
|
be used for.<P>
|
|
<P>
|
|
Cost to Implementors:<P>
|
|
<P>
|
|
Minimal. Implementations could continue to support COMPILER-LET as<P>
|
|
an extension.<P>
|
|
<P>
|
|
Cost to Users:<P>
|
|
<P>
|
|
Code currently depending on this feature is either non-existent or<P>
|
|
already not portable (due to wide variation in implementation <P>
|
|
strategy for COMPILER-LET).<P>
|
|
<P>
|
|
People who use COMPILER-LET would have to rewrite their programs to use<P>
|
|
some other construct. As discussed above, most uses of COMPILER-LET<P>
|
|
for communication between macros can be handled using <A REL=DEFINITION HREF="../Body/s_flet_.htm#macrolet"><B>MACROLET</B></A> or<P>
|
|
<A REL=DEFINITION HREF="../Body/s_symbol.htm#symbol-macrolet"><B>SYMBOL-MACROLET</B></A>, though some perspicuity may be lost in the process.<P>
|
|
<P>
|
|
<P>
|
|
<B>Current Practice:<P>
|
|
</B> <P>
|
|
Some implementations have implemented the description in CLtL. <P>
|
|
Users of those implementations (quite reasonably) can't figure how to <P>
|
|
use COMPILER-LET and so don't use it much.<P>
|
|
<P>
|
|
Some implementations whose interpreters include a preprocessor to<P>
|
|
expand all macros have already implemented something similar to proposal<P>
|
|
COMPILER-LET-CONFUSION:REPAIR. Users of such implementations<P>
|
|
probably use COMPILER-LET somewhat more often since it has an<P>
|
|
intelligible behavior, but their code is not portable since it relies<P>
|
|
on behaviors which are either contrary to or not guaranteed by CLtL.<P>
|
|
<P>
|
|
<B>Benefits:<P>
|
|
</B><P>
|
|
Either way, a potential area of incompatibility between compiled and<P>
|
|
interpreted code would be eliminated.<P>
|
|
<P>
|
|
Either way, a potential area of portability trouble would be very<P>
|
|
drastically reduced (in the case of the REPAIR option) or eliminated<P>
|
|
(in the case of the ELIMINATE option).<P>
|
|
<P>
|
|
<B>Discussion:<P>
|
|
</B><P>
|
|
Pitman strongly favors COMPILER-LET-CONFUSION:REPAIR. He argues <P>
|
|
against the idea of using <A REL=DEFINITION HREF="../Body/s_flet_.htm#macrolet"><B>MACROLET</B></A> instead of COMPILER-LET, saying:<P>
|
|
<P>
|
|
This is a little misleading because it's like saying you can<P>
|
|
do without <A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> given that you have <A REL=DEFINITION HREF="../Body/s_flet_.htm#flet"><B>FLET</B></A>. You can, but you lose some things<P>
|
|
in the process:<P>
|
|
<P>
|
|
Just as rewriting a <A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> using <A REL=DEFINITION HREF="../Body/s_flet_.htm#flet"><B>FLET</B></A> might slow your computation, so too<P>
|
|
a rewrite of COMPILER-LET using <A REL=DEFINITION HREF="../Body/s_flet_.htm#macrolet"><B>MACROLET</B></A> might slow things down. However,<P>
|
|
compilation speed is generally not weighted as heavily as execution speed<P>
|
|
by many people, so the loss of speed here may not be as important.<P>
|
|
<P>
|
|
Just as rewriting a <A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> using <A REL=DEFINITION HREF="../Body/s_flet_.htm#flet"><B>FLET</B></A> might obscure the simplicity of your<P>
|
|
intent, so too rewriting COMPILER-LET using <A REL=DEFINITION HREF="../Body/s_flet_.htm#macrolet"><B>MACROLET</B></A> might obscure your<P>
|
|
intent. You'd probably get used to recognizing idioms if you used it often<P>
|
|
enough. Certainly this would be true if you didn't have <A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A>. However,<P>
|
|
COMPILER-LET is used less often, so not having it would mean that the<P>
|
|
code you wrote instead would be much harder to read because people<P>
|
|
wouldn't have the necessary familiarity with the idioms involved and so<P>
|
|
wouldn't always understand them.<P>
|
|
<P>
|
|
Sandra Loosemore responds:<P>
|
|
<P>
|
|
The argument that using <A REL=DEFINITION HREF="../Body/s_flet_.htm#macrolet"><B>MACROLET</B></A> is more inefficient than COMPILER-LET<P>
|
|
is questionable. Both of the suggested implementation techniques for<P>
|
|
COMPILER-LET involve considerable overhead.<P>
|
|
<P>
|
|
If COMPILER-LET were not part of the language, people wouldn't think in<P>
|
|
terms of rewriting COMPILER-LETs as MACROLETs; instead, they'd think of<P>
|
|
how to use <A REL=DEFINITION HREF="../Body/s_flet_.htm#macrolet"><B>MACROLET</B></A> in the first place to solve their problems. This<P>
|
|
is what people who now use implementations with broken COMPILER-LETs<P>
|
|
already do. Since <A REL=DEFINITION HREF="../Body/s_flet_.htm#macrolet"><B>MACROLET</B></A> is now used much more frequently than<P>
|
|
COMPILER-LET, that argues that people are much more familiar with <P>
|
|
<A REL=DEFINITION HREF="../Body/s_flet_.htm#macrolet"><B>MACROLET</B></A> idioms than COMPILER-LET idioms.<P>
|
|
<P>
|
|
Also, note that the intent of the revised COMPILER-LET definition is<P>
|
|
to make the binding only lexically visible within the body. Using<P>
|
|
special binding for this purpose is troublesome. Both the <A REL=DEFINITION HREF="../Body/s_flet_.htm#macrolet"><B>MACROLET</B></A><P>
|
|
and <A REL=DEFINITION HREF="../Body/s_symbol.htm#symbol-macrolet"><B>SYMBOL-MACROLET</B></A> solutions are completely lexical and avoid all<P>
|
|
the problems associated with special binding.<P>
|
|
<P>
|
|
Glenn Burke thinks it needs to be emphasized that the code-walker<P>
|
|
mentioned in the REPAIR proposal does not need to be portable. He<P>
|
|
says:<P>
|
|
<P>
|
|
The present wording makes it sound like a piece of cake to do with<P>
|
|
portable code, when the reality is that a good fraction of CL cleanup<P>
|
|
effort has involved the lack of capability of producing such a beast.<P>
|
|
Without one or more of a number of proposals being accepted, a fully<P>
|
|
correct portable code walker cannot be built, in my belief.<P>
|
|
<P>
|
|
I object to the flippant attitude of just "presupposing" this<P>
|
|
"trivial" function which "we know how to do".<P>
|
|
<P>
|
|
We have considered a number of other options on this issue, including<P>
|
|
a variety of proposals that would redefine COMPILER-LET to store<P>
|
|
information about the variable bindings in the lexical environment, and<P>
|
|
either having <A REL=DEFINITION HREF="../Body/f_mexp_.htm#macroexpand-1"><B>MACROEXPAND-1</B></A> make the special bindings or <A REL=DEFINITION HREF="../Body/f_provid.htm#provide"><B>provide</B></A> a<P>
|
|
function which could be used to access them directly.<P>
|
|
<P>
|
|
Kent Pitman says:<P>
|
|
People have suggested that if it comes to making an incompatible change<P>
|
|
on this one, it's probably better to just remove the feature and let<P>
|
|
people continue to <A REL=DEFINITION HREF="../Body/f_provid.htm#provide"><B>provide</B></A> it compatibly where they think it's useful.<P>
|
|
Even though I think the COMPILER-SYMBOL-VALUE thing is technically<P>
|
|
doable, I find myself swayed by arguments that it's not the correct<P>
|
|
avenue for us to pursue at this time.<P>
|
|
<P>
|
|
David Moon says:<P>
|
|
I think COMPILER-LET-CONFUSION:REPAIR should be split into four proposals.<P>
|
|
First, one that gives the general framework for repairing but doesn't<P>
|
|
say anything about how the interpreter implements COMPILER-LET, other<P>
|
|
than to say that an additional proposal is needed to cover that. Then<P>
|
|
three proposals for how the interpreter implements COMPILER-LET:<P>
|
|
(1) The interpreter always does a "semantic pre-pass" like the compiler.<P>
|
|
(2) The interpreter expands all macros inside COMPILER-LET before<P>
|
|
evaluating any of the code inside COMPILER-LET.<P>
|
|
(3) COMPILER-LET passes the variable bindings to <A REL=DEFINITION HREF="../Body/f_mexp_.htm#macroexpand-1"><B>MACROEXPAND-1</B></A><P>
|
|
through the lexical environment, and the time when the interpreter<P>
|
|
expands macros is not changed.<P>
|
|
</PRE>
|
|
<HR>
|
|
|
|
<A REL=NAVIGATOR HREF="../Front/StartPts.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Starting Points]" SRC="../Graphics/StartPts.gif" ALIGN=Bottom></A><A REL=TOC HREF="../Front/Contents.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Contents]" SRC="../Graphics/Contents.gif" ALIGN=Bottom></A><A REL=INDEX HREF="../Front/X_Master.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Index]" SRC="../Graphics/Index.gif" ALIGN=Bottom></A><A REL=INDEX HREF="../Front/X_Symbol.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Symbols]" SRC="../Graphics/Symbols.gif" ALIGN=Bottom></A><A REL=GLOSSARY HREF="../Body/26_a.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Glossary]" SRC="../Graphics/Glossary.gif" ALIGN=Bottom></A><A HREF="../Front/X3J13Iss.htm"><IMG WIDTH=80 HEIGHT=40 ALT="[Issues]" SRC="../Graphics/Issues.gif" ALIGN=Bottom></A><BR>
|
|
|
|
<A REL=COPYRIGHT HREF="../Front/Help.htm#Legal"><I>Copyright 1996-2005, LispWorks Ltd. All rights reserved.</I></A><P>
|
|
</BODY>
|
|
</HTML>
|