1
0
Fork 0
cl-sites/HyperSpec-7-0/HyperSpec/Issues/iss092_w.htm
2024-04-01 10:24:07 +02:00

384 lines
28 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 DECLARATION-SCOPE 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/iss091_w.htm">
<LINK REL=UP HREF="../Issues/iss092.htm">
<LINK REL=NEXT HREF="../Issues/iss093_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/iss091_w.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Previous]" SRC="../Graphics/Prev.gif" ALIGN=Bottom></A><A REL=UP HREF="../Issues/iss092.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Up]" SRC="../Graphics/Up.gif" ALIGN=Bottom></A><A REL=NEXT HREF="../Issues/iss093_w.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Next]" SRC="../Graphics/Next.gif" ALIGN=Bottom></A></H1>
<HR>
<H2>Issue DECLARATION-SCOPE Writeup</H2>
<PRE>Proposal <A HREF="iss092.htm">DECLARATION-SCOPE:NO-HOISTING</A> was accepted at the January 1989 meeting.<P>
<P>
<B>Issue:</B> <A HREF="iss092.htm">DECLARATION-SCOPE</A><P>
<P>
<B>References:</B> Declaration Syntax (CLtL, Section 9.1, pp. 153-157)<P>
LAMBDA-Expressions (CLtL, Section 5.2.2, pp. 59-66)<P>
Cleanup issue <A HREF="iss159_m.htm">FLET-DECLARATIONS</A> (accepted)<P>
Cleanup issue <A HREF="iss096.htm">DECLARE-TYPE-FREE</A> (accepted)<P>
<P>
<B>Category:</B> CHANGE/CLARIFICATION<P>
<P>
<B>Edit history:</B> V1: Hornig@Symbolics.COM -- 5 January 1988<P>
Version 2, Moon, 2-Feb-1988 (edits based on discussion)<P>
Version 3, Moon, 18-Sep-88, for private discussion between JonL and Moon<P>
Version 4, JonL, 15-Nov-88 add 2nd proposal; major rewrite.<P>
<P>
<P>
<B>Problem description:<P>
</B><P>
The description of the scope of declarations made with <A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>DECLARE</B></A> is <P>
unclear (although unambiguous) and arguably a mistake. At issue is<P>
whether the scope of some or all of the declarations at the head of<P>
a special form includes code appearing in any non-body part of that <P>
special form. CLtL p.155 attempts to address the issue by classifying <P>
declarations into two classes -- &quot;pervasive&quot; and &quot;non-pervasive&quot; -- but <P>
it does not succeed very well.<P>
<P>
A particular question of interest is whether the initial value forms for <P>
<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A>, <A REL=DEFINITION HREF="../Body/s_let_l.htm#letST"><B>LET*</B></A>, <A REL=DEFINITION HREF="../Body/s_flet_.htm#flet"><B>FLET</B></A>, <A REL=DEFINITION HREF="../Body/s_flet_.htm#labels"><B>LABELS</B></A>, <A REL=DEFINITION HREF="../Body/m_do_do.htm#do"><B>DO</B></A>, <A REL=DEFINITION HREF="../Body/m_prog_.htm#prog"><B>PROG</B></A> etc. are included. The rules of CLtL,<P>
on some cases, are clear enough to see that a declaration inside the <P>
special form is &quot;hoisted&quot; up and around the whole form, so as to include <P>
all the &quot;initial value&quot; forms (and &quot;stepper&quot; forms and &quot;result&quot; forms for <P>
those constructs that have them). This means that lexical argument <P>
variable X in the following function is inaccessible inside the initial <P>
value forms of the LET:<P>
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>defun</B></A> bar (x y) ;[1] 1st instance of x<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>let</B></A> ((old-x x) ;[2] 2nd instance of x -- same as 1st instance?<P>
(x y)) ;[3] 3rd instance<P>
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>declare</B></A> (<A REL=DEFINITION HREF="../Body/d_specia.htm#special"><B>special</B></A> x))<P>
(<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>list</B></A> old-x x)))<P>
The declaration intended for the binding of X[3] also alters the<P>
scoping of the reference of X[2]; likely, this was not an intended <P>
consequence. [This is a simplification of the example on CLtL p.155].<P>
<P>
In this discussion, the term &quot;body&quot; will include any &quot;stepper&quot; or <P>
&quot;result&quot; forms, such as might be found in a <A REL=DEFINITION HREF="../Body/m_do_do.htm#do"><B>DO</B></A> or DO-mumble-SYMBOLS<P>
construct. The reasoning for this is that such forms are always <P>
included in the scope of all name bindings (if any) being established <P>
by the special form. They form an extended part of the &quot;body&quot;.<P>
<P>
<P>
<P>
Proposal (<A HREF="iss092.htm">DECLARATION-SCOPE:NO-HOISTING</A>)<P>
<P>
Specify that the scope of a declaration located at the head of a special <P>
form or <A REL=DEFINITION HREF="../Body/a_lambda.htm#lambda"><B>lambda</B></A> expression is as follows:<P>
(1) it always includes the body forms [as well as any &quot;stepper&quot; or <P>
&quot;result&quot; forms]<P>
(2) it also includes the scope of the name binding, if any, to which <P>
it applies [LET, <A REL=DEFINITION HREF="../Body/a_lambda.htm#lambda"><B>LAMBDA</B></A>, <A REL=DEFINITION HREF="../Body/s_flet_.htm#flet"><B>FLET</B></A>, <A REL=DEFINITION HREF="../Body/m_do_do.htm#do"><B>DO</B></A>, etc. introduce &quot;name bindings&quot;; <P>
<A REL=DEFINITION HREF="../Body/s_locall.htm#locally"><B>LOCALLY</B></A> doesn't.];<P>
<P>
This very straightforward prescription depends on one rather subtle<P>
point, namely that the scope of name bindings is an already solved<P>
question. Whether or not a particular declaration affects an initial<P>
value form (such as for <A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> or <A REL=DEFINITION HREF="../Body/s_let_l.htm#letST"><B>LET*</B></A>) depends _solely_ on whether it is<P>
applied to a variable or function (name) being bound whose scope<P>
includes such forms. In this sense, the above specification limits the<P>
scope of declarations for name bindings to be exactly the scope of the<P>
name binding itself -- i.e. &quot;like variable&quot;. Thus there would be no<P>
&quot;hoisting&quot; of the special declarations in the example cited in the<P>
problem description. [See the Discussion section for a review of the <P>
CL rules on variable/function-name scoping in special forms.]<P>
<P>
Those declarations not correlated with any name binding do not cover any<P>
of the initial-value forms; their scope simply includes the body (as well <P>
as any &quot;stepper&quot; or &quot;result&quot; forms). In a sense, the above specification <P>
limits the scope of these kinds of declarations to be the same as an<P>
arbitrary name binding in a <A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> or <A REL=DEFINITION HREF="../Body/s_flet_.htm#flet"><B>FLET</B></A> construct -- i.e. &quot;like variable&quot;.<P>
[See also the issue <A HREF="iss096.htm">DECLARE-TYPE-FREE</A>.]<P>
<P>
Thus there is to be no &quot;hoisting&quot; for declarations in special forms or <P>
<A REL=DEFINITION HREF="../Body/a_lambda.htm#lambda"><B>lambda</B></A> expressions; the only initial value forms affected by a declaration <P>
will be those included indirectly, by the effect, if any, that a <P>
declaration has on a name binding. <P>
<P>
A question may arise as to what it means for a declaration to &quot;apply to&quot;, <P>
or &quot;be correlated to&quot; a name binding. As stated above about variable<P>
scoping, this is an already solved question in Common Lisp; it is not <P>
the purpose of this proposal to alter, clarify or in any other way bear <P>
upon the basic _applicability_ rules of declarations in Common Lisp. <P>
However, a few reminders about these rules will help one understand the <P>
above specification:<P>
-- <A REL=DEFINITION HREF="../Body/d_specia.htm#special"><B>SPECIAL</B></A> and <A REL=DEFINITION HREF="../Body/a_type.htm#type"><B>TYPE</B></A> declarations never apply to function bindings;<P>
-- <A REL=DEFINITION HREF="../Body/d_inline.htm#inline"><B>INLINE</B></A> and <A REL=DEFINITION HREF="../Body/d_ftype.htm#ftype"><B>FTYPE</B></A> declarations never apply to variable bindings; <P>
-- <A REL=DEFINITION HREF="../Body/d_optimi.htm#optimize"><B>OPTIMIZE</B></A> never applies to either kind of binding;<P>
-- (&lt;declaration&gt; X) never applies to a binding of Y.<P>
The specific rules are for the most part distributed throughout the <P>
individual declaration definitions. The name-applicibility issue for <P>
bindings must be specified independently of how the declaration scoping <P>
issue is decided, and should not be confused with that scoping issue.<P>
<P>
<P>
<P>
Proposal (DECLARATION-SCOPE:LIMITED-HOISTING)<P>
<P>
Specify that the scope of a declaration located at the head of a special <P>
form or <A REL=DEFINITION HREF="../Body/a_lambda.htm#lambda"><B>lambda</B></A> expression is as follows:<P>
(1) it always includes the body forms [as well as any &quot;stepper&quot; or <P>
&quot;result&quot; forms]<P>
(2) if the declaration is applicable to a name binding in that form,<P>
then it is limited to exactly the scope of that name binding [LET, <P>
<A REL=DEFINITION HREF="../Body/a_lambda.htm#lambda"><B>LAMBDA</B></A>, <A REL=DEFINITION HREF="../Body/s_flet_.htm#flet"><B>FLET</B></A>, etc. introduce &quot;name bindings&quot;; <A REL=DEFINITION HREF="../Body/s_locall.htm#locally"><B>LOCALLY</B></A> doesn't.];<P>
(3) if the declaration is not applicable to a name binding in that form,<P>
then it includes all the initial value forms, in addition to the<P>
body forms.<P>
<P>
This very straightforward prescription depends on one rather subtle <P>
point, namely that the scope of name bindings is an already solved <P>
question. This applies not only to <A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> and <A REL=DEFINITION HREF="../Body/s_let_l.htm#letST"><B>LET*</B></A> variables, but to the <P>
&amp;optional, &amp;key and &amp;aux variables of LAMBDA-Expressions. In this sense, <P>
the above specification limits the scope of declarations for name bindings <P>
to be exactly the scope of the name binding itself. Thus there would be <P>
no &quot;hoisting&quot; of the special declarations in the example cited in the<P>
problem description.<P>
<P>
Those declarations not correlated with any name binding act as if they<P>
were included in a new <A REL=DEFINITION HREF="../Body/s_locall.htm#locally"><B>LOCALLY</B></A> construct wrapped around the entire<P>
special form. Thus they are not scoped like an arbitrary variable<P>
(or, &quot;name binding&quot;) in that special form, but rather are &quot;hoisted&quot; up.<P>
<P>
Whether or not a declaration is &quot;hoisted&quot; up around the special form in <P>
which it occurs depends on whether or not it is &quot;captured en passant&quot; by <P>
a correlated name binding.<P>
<P>
A question may arise as to what it means for a declaration to &quot;apply to&quot;, <P>
or &quot;be correlated to&quot; a name binding. As stated above about variable<P>
scoping, this is an already solved question in Common Lisp; it is not <P>
the purpose of this proposal to alter, clarify or in any other way bear <P>
upon the basic _applicability_ rules of declarations in Common Lisp. <P>
However, a few reminders about these rules will help one understand the <P>
above specification:<P>
-- <A REL=DEFINITION HREF="../Body/d_specia.htm#special"><B>SPECIAL</B></A> and <A REL=DEFINITION HREF="../Body/a_type.htm#type"><B>TYPE</B></A> declarations never apply to function bindings;<P>
-- <A REL=DEFINITION HREF="../Body/d_inline.htm#inline"><B>INLINE</B></A> and <A REL=DEFINITION HREF="../Body/d_ftype.htm#ftype"><B>FTYPE</B></A> declarations never apply to variable bindings; <P>
-- <A REL=DEFINITION HREF="../Body/d_optimi.htm#optimize"><B>OPTIMIZE</B></A> never applies to either kind of binding;<P>
-- (&lt;declaration&gt; X) never applies to a binding of Y.<P>
The specific rules are for the most part distributed throughout the <P>
individual declaration definitions. The name-applicibility issue for <P>
bindings must be specified independently of how the declaration scoping <P>
issue is decided, and should not be confused with that scoping issue.<P>
<P>
<P>
<B>Examples:<P>
</B><P>
;;; The following example is from a common-lisp mailing list discussion<P>
;;; (from code suggested by Pavel Curtis). The question is whether or<P>
;;; not the special declaration in FOO applies to the (<A REL=DEFINITION HREF="../Body/f_1pl_1_.htm#1PL"><B>1+</B></A> x) form.<P>
<P>
(<A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>setf</B></A> (<A REL=DEFINITION HREF="../Body/f_symb_5.htm#symbol-value"><B>symbol-value</B></A> 'x) 6)<P>
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>defun</B></A> foo (x) ;a lexical binding of X<P>
(<A REL=DEFINITION HREF="../Body/f_wr_pr.htm#print"><B>print</B></A> x)<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>let</B></A> ((x (<A REL=DEFINITION HREF="../Body/f_1pl_1_.htm#1PL"><B>1+</B></A> x))) ;is <A REL=DEFINITION HREF="../Body/s_the.htm#the"><B>the</B></A> <A REL=DEFINITION HREF="../Body/f_firstc.htm#second"><B>second</B></A> X <A REL=DEFINITION HREF="../Body/d_specia.htm#special"><B>special</B></A> <A REL=DEFINITION HREF="../Body/a_or.htm#or"><B>or</B></A> not?<P>
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>declare</B></A> (<A REL=DEFINITION HREF="../Body/d_specia.htm#special"><B>special</B></A> x)) ;`normal' <A REL=DEFINITION HREF="../Body/d_declar.htm#declaration"><B>declaration</B></A><P>
(bar))<P>
(<A REL=DEFINITION HREF="../Body/f_1pl_1_.htm#1PL"><B>1+</B></A> x))<P>
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>defun</B></A> bar () (<A REL=DEFINITION HREF="../Body/f_wr_pr.htm#print"><B>print</B></A> (<A REL=DEFINITION HREF="../Body/s_locall.htm#locally"><B>locally</B></A> (<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>declare</B></A> (<A REL=DEFINITION HREF="../Body/d_specia.htm#special"><B>special</B></A> x)) x)))<P>
<P>
(foo 10) will printout of 10 and 11 by either proposal herein<P>
(foo 10) will printout of 10 and 7 by CLtL style &quot;hoisting&quot;<P>
<P>
<P>
;;; The following example is due to Jim Boyce, of Lucid Inc. It shows how<P>
;;; the &quot;hoisting&quot; of the declaration inadvertently causes it to act more<P>
;;; like a proclamation than a declaration; namely, the declaration is<P>
;;; applied to two different variables (which happen to have the same<P>
;;; name) -- the first variable is the lexical one bound on line [1] and<P>
;;; the second variables is bound on line [3]. Whereas lexical scoping<P>
;;; rules would say that the reference in line [2] is to the variable<P>
;;; bound on line [1], the effect of the &quot;hoisted&quot; declaration is to<P>
;;; make the line [1]'s variable inaccessible in the initial value forms.<P>
<P>
(<A REL=DEFINITION HREF="../Body/a_setf.htm#setf"><B>setf</B></A> (<A REL=DEFINITION HREF="../Body/f_symb_5.htm#symbol-value"><B>symbol-value</B></A> 'x) 6)<P>
<P>
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>defun</B></A> bar (x y) ;[1] 1st instance of x<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>let</B></A> ((old-x x) ;[2] 2nd instance of x -- same as 1st instance?<P>
(x y)) ;[3] 3rd instance<P>
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>declare</B></A> (<A REL=DEFINITION HREF="../Body/d_specia.htm#special"><B>special</B></A> x))<P>
(<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>list</B></A> old-x x)))<P>
<P>
(bar 'first 'second) ==&gt; (first second) ;by either proposal herein<P>
(bar 'first 'second) ==&gt; (6 second) ;by &quot;hoisting&quot;, a la CLtL.<P>
<P>
<P>
<B>Rationale:<P>
</B><P>
These semantics are simpler to understand. Almost everyone feels that<P>
the example of CLtL p.155 is very unnatural. LIMITED-HOISTING is less <P>
of a change to CLtL semantics; but NO-HOISTING seems more natural to <P>
most people since it restores a closer equivalence between <A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> forms <P>
and LAMBDA-expressions. Also, several vendors report that customers <P>
frequently seem to assume the semantics of NO-HOISTING.<P>
<P>
<P>
<B>Current practice:<P>
</B><P>
Most implementations implement the rules in CLtL, as exemplified by<P>
the example on p.155. Symbolics currently implements rules based on<P>
Zetalisp which are different from both this proposal and Common Lisp.<P>
Symbolics plans to change to Common Lisp rules in the future.<P>
<P>
<P>
<B>Cost to Implementors:<P>
</B><P>
Modest; some minor fixes will be necessary to to compilers, interpreters <P>
and &quot;code walkers&quot; that parse declarations.<P>
<P>
<P>
<B>Cost to Users:<P>
</B><P>
Modest. It is mostly moot since users tend to avoid the &quot;hoisting&quot;<P>
situations on special declarations.<P>
<P>
It is possible to mechanically examine a program to determine whether<P>
its behavior would change under the new rules. This permits an<P>
implementation to <A REL=DEFINITION HREF="../Body/f_provid.htm#provide"><B>provide</B></A> a transition tool to ease conversion to the<P>
new definition.<P>
<P>
<P>
<B>Cost of non-adoption:<P>
</B><P>
Serious non-portability of code, since not every implementor seems to <P>
agree on how to read the disputed rules of CLtL pp. 153-157; continuing<P>
confusion in the user community.<P>
<P>
<P>
<B>Performance impact:<P>
</B><P>
None.<P>
<P>
<B>Benefits:<P>
</B><P>
Elimination of confusion; increase of portability between implementations.<P>
<P>
<P>
<B>Esthetics:<P>
</B><P>
Simplifies the scoping issue; eliminates special-case scoping rules for<P>
<A REL=DEFINITION HREF="../Body/d_specia.htm#special"><B>SPECIAL</B></A> declarations.<P>
<P>
<P>
<P>
<B>Discussion:<P>
</B><P>
Only the <A REL=DEFINITION HREF="../Body/d_specia.htm#special"><B>SPECIAL</B></A> declaration has semantic import for CL; both<P>
proposals specify an incompatible change for this case, to &quot;retract&quot;<P>
the expansive scope stated or implied in CLtL. All other declarations<P>
are considered &quot;advice&quot; to an optimizing compiler, and should have<P>
no semantic effect on correct programs. However, programmers making<P>
use of such declarations may notice a larger difference in the<P>
NO-HOISTING proposal, since some of their <A REL=DEFINITION HREF="../Body/d_inline.htm#inline"><B>INLINE</B></A>, <A REL=DEFINITION HREF="../Body/d_optimi.htm#optimize"><B>OPTIMIZE</B></A>, <A REL=DEFINITION HREF="../Body/a_type.htm#type"><B>TYPE</B></A>,<P>
etc. declarations will no longer apply to the initial-value forms.<P>
<P>
<P>
One idiom which will be adversely affected by both of these proposals is:<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>let</B></A> ((*a* *a*))<P>
;; rebind *a* to it's &quot;old&quot; value<P>
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>declare</B></A> (<A REL=DEFINITION HREF="../Body/d_specia.htm#special"><B>special</B></A> *a*))<P>
...)<P>
where *a* has not been proclaimed special. This idiom would likely<P>
have to be written as:<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>let</B></A> ((*a* (<A REL=DEFINITION HREF="../Body/s_locall.htm#locally"><B>locally</B></A> (<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>declare</B></A> (<A REL=DEFINITION HREF="../Body/d_specia.htm#special"><B>special</B></A> *a*)) *a*)))<P>
;; rebind *a* to it's &quot;old&quot; value<P>
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>declare</B></A> (<A REL=DEFINITION HREF="../Body/d_specia.htm#special"><B>special</B></A> *a*))<P>
...)<P>
or [preferably!] *a* should be proclaimed special. Similar idiots <P>
like this may be in use for LAMBDA-Expressions, or DEFUNs etc.<P>
<P>
<P>
On the other hand, the inadvertent &quot;shadowing&quot; which prevents the <P>
following <A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A>'s initial value forms from referencing the input argument<P>
is handily solved by either proposal herein. If neither of these <P>
<B>proposals is not adopted, then the intent of the code for BAR:<P>
</B> (<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>defun</B></A> bar (x y) ;[1] 1st instance of x<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>let</B></A> ((old-x x) ;[2] 2nd instance of x -- same as 1st instance?<P>
(x y)) ;[3] 3rd instance<P>
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>declare</B></A> (<A REL=DEFINITION HREF="../Body/d_specia.htm#special"><B>special</B></A> x))<P>
(<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>list</B></A> old-x x)))<P>
would likely have to be expressed by introducing new <A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A> contours:<P>
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>defun</B></A> bar (x y) ;[1] 1st instance of x<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>let</B></A> ((old-x x)) ;[2] 2nd instance of x -- same as 1st instance?<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>let</B></A> ((x y)) ;[3] 3rd instance<P>
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>declare</B></A> (<A REL=DEFINITION HREF="../Body/d_specia.htm#special"><B>special</B></A> x))<P>
(<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>list</B></A> old-x x))))<P>
<P>
<P>
The source of additional confusion has long been that <A REL=DEFINITION HREF="../Body/a_type.htm#type"><B>TYPE</B></A> declarations <P>
had to be treated differently from all other declarations; this was because <P>
of the prohibition found on p158 of CLtL. Given the acceptance of the<P>
<A HREF="iss096.htm">DECLARE-TYPE-FREE</A> proposal, it no longer is necessary to make an exception <P>
for it, nor to categorize declarations into &quot;pervasive&quot; and &quot;non-pervasive&quot;, <P>
or &quot;free&quot; and &quot;bound&quot;.<P>
<P>
<P>
It is not the purpose of this proposal to alter, clarify or in any <P>
other way bear upon the scoping rules of variables in Common Lisp.<P>
However, a few reminders about these rules will help one understand <P>
the above prescription. Except <A REL=DEFINITION HREF="../Body/s_let_l.htm#letST"><B>LET*</B></A>, <A REL=DEFINITION HREF="../Body/m_prog_.htm#progST"><B>PROG*</B></A>, <A REL=DEFINITION HREF="../Body/m_do_do.htm#doST"><B>DO*</B></A>, <A REL=DEFINITION HREF="../Body/s_flet_.htm#labels"><B>LABELS</B></A>, and <A REL=DEFINITION HREF="../Body/s_flet_.htm#macrolet"><B>MACROLET</B></A>,<P>
all the other special forms of CLtL p154 which admit declarations have <P>
the property that the scope of the name binding does not include any<P>
initial value form. As a review of these scopes, note:<P>
-- for <A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>LET</B></A>, <A REL=DEFINITION HREF="../Body/s_flet_.htm#flet"><B>FLET</B></A>, <A REL=DEFINITION HREF="../Body/m_multip.htm#multiple-value-bind"><B>MULTIPLE-VALUE-BIND</B></A>, none of the initial value <P>
forms are included in the variables' (or functions') scope;<P>
-- for DO-&lt;mumble&gt;-SYMBOLS, the initial value forms are not included,<P>
but the optional result forms are included;<P>
-- for <A REL=DEFINITION HREF="../Body/m_do_do.htm#do"><B>DO</B></A>, <A REL=DEFINITION HREF="../Body/m_dolist.htm#dolist"><B>DOLIST</B></A>, and <A REL=DEFINITION HREF="../Body/m_dotime.htm#dotimes"><B>DOTIMES</B></A>, the initial value forms are not <P>
included, but the stepper forms and the optional result forms <P>
are included;<P>
-- for <A REL=DEFINITION HREF="../Body/s_let_l.htm#letST"><B>LET*</B></A>, <A REL=DEFINITION HREF="../Body/m_prog_.htm#progST"><B>PROG*</B></A>, and <A REL=DEFINITION HREF="../Body/m_do_do.htm#doST"><B>DO*</B></A>, a variable's scope also includes the <P>
remaining initial value forms, for subsequent variable bindings;<P>
-- for <A REL=DEFINITION HREF="../Body/s_flet_.htm#labels"><B>LABELS</B></A> and <A REL=DEFINITION HREF="../Body/s_flet_.htm#macrolet"><B>MACROLET</B></A>, a function name's scope includes all the <P>
code forms for the functions being defined by the special form <P>
[a compiler writer must know how not to get into an infinite loop <P>
of substitutions when there are 'in-line' declarations on these <P>
mutually recursive names];<P>
-- for a <A REL=DEFINITION HREF="../Body/a_lambda.htm#lambda"><B>LAMBDA</B></A> application, none of the explicit value forms are <P>
included in the bound variable scoping; however, the 'initform'<P>
code (if any) for &amp;optional, &amp;key, and &amp;aux bindings are included <P>
in the same way as <A REL=DEFINITION HREF="../Body/s_let_l.htm#letST"><B>LET*</B></A> does;<P>
-- for <A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>DEFUN</B></A>, <A REL=DEFINITION HREF="../Body/m_defmac.htm#defmacro"><B>DEFMACRO</B></A>, <A REL=DEFINITION HREF="../Body/m_deftp.htm#deftype"><B>DEFTYPE</B></A> and <A REL=DEFINITION HREF="../Body/m_defset.htm#defsetf"><B>DEFSETF</B></A> follow the rules for<P>
LAMBDA-Expressions (CLtL, Section 5.2.2, pp. 59-66).<P>
<P>
Remember also that new name bindings &quot;shadow&quot; (after a fashion) any <P>
higher level binding or declarations. E.g., presuming that no <P>
proclamations are in effect, consider the inner let bindings of:<P>
(<A REL=DEFINITION HREF="../Body/s_locall.htm#locally"><B>locally</B></A> (<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>declare</B></A> (<A REL=DEFINITION HREF="../Body/d_specia.htm#special"><B>special</B></A> x) (<A REL=DEFINITION HREF="../Body/a_float.htm#float"><B>float</B></A> y)) <P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#let"><B>let</B></A> ((x 5) (y 10)) <P>
(<A REL=DEFINITION HREF="../Body/f_wr_pr.htm#print"><B>print</B></A> (+ x y))))<P>
then x is bound as local (not special); and y is bound with no particular<P>
type information [because the 'y' being bound is a different variable<P>
than the 'y' declared float in the outer scope].<P>
<P>
<P>
It has been suggested that compilers could be a bit more helpful in <P>
detecting anomalous bindings, such as in the <A REL=DEFINITION HREF="../Body/s_let_l.htm#letST"><B>LET*</B></A> following:<P>
(<A REL=DEFINITION HREF="../Body/m_defun.htm#defun"><B>defun</B></A> bar (x y)<P>
(<A REL=DEFINITION HREF="../Body/s_let_l.htm#letST"><B>let*</B></A> ((old-x x)<P>
(x y)<P>
(new-x x))<P>
(<A REL=DEFINITION HREF="../Body/s_declar.htm#declare"><B>declare</B></A> (<A REL=DEFINITION HREF="../Body/d_specia.htm#special"><B>special</B></A> x))<P>
(<A REL=DEFINITION HREF="../Body/a_list.htm#list"><B>list</B></A> old-x x new-x)))<P>
The collection of variables named X in the <A REL=DEFINITION HREF="../Body/s_let_l.htm#letST"><B>LET*</B></A> binding and initial<P>
forms includes both local (lexical) and special ones.<P>
<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>