384 lines
28 KiB
HTML
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 -- "pervasive" and "non-pervasive" -- 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 "hoisted" up and around the whole form, so as to include <P>
|
|
all the "initial value" forms (and "stepper" forms and "result" 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 "body" will include any "stepper" or <P>
|
|
"result" 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 "body".<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 "stepper" or <P>
|
|
"result" 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 "name bindings"; <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. "like variable". Thus there would be no<P>
|
|
"hoisting" 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 "stepper" or "result" 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. "like variable".<P>
|
|
[See also the issue <A HREF="iss096.htm">DECLARE-TYPE-FREE</A>.]<P>
|
|
<P>
|
|
Thus there is to be no "hoisting" 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 "apply to", <P>
|
|
or "be correlated to" 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>
|
|
-- (<declaration> 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 "stepper" or <P>
|
|
"result" 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 "name bindings"; <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>
|
|
&optional, &key and &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 "hoisting" 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, "name binding") in that special form, but rather are "hoisted" up.<P>
|
|
<P>
|
|
Whether or not a declaration is "hoisted" up around the special form in <P>
|
|
which it occurs depends on whether or not it is "captured en passant" by <P>
|
|
a correlated name binding.<P>
|
|
<P>
|
|
A question may arise as to what it means for a declaration to "apply to", <P>
|
|
or "be correlated to" 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>
|
|
-- (<declaration> 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 "hoisting"<P>
|
|
<P>
|
|
<P>
|
|
;;; The following example is due to Jim Boyce, of Lucid Inc. It shows how<P>
|
|
;;; the "hoisting" 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 "hoisted" 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) ==> (first second) ;by either proposal herein<P>
|
|
(bar 'first 'second) ==> (6 second) ;by "hoisting", 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 "code walkers" that parse declarations.<P>
|
|
<P>
|
|
<P>
|
|
<B>Cost to Users:<P>
|
|
</B><P>
|
|
Modest. It is mostly moot since users tend to avoid the "hoisting"<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 "retract"<P>
|
|
the expansive scope stated or implied in CLtL. All other declarations<P>
|
|
are considered "advice" 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 "old" 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 "old" 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 "shadowing" 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 "pervasive" and "non-pervasive", <P>
|
|
or "free" and "bound".<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-<mumble>-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 &optional, &key, and &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 "shadow" (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>
|