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

85 lines
9.8 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: Section 3.1.4</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="03_ac.htm">
<LINK REL=UP HREF="03_a.htm">
<LINK REL=NEXT HREF="03_ae.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="03_ac.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Previous]" SRC="../Graphics/Prev.gif" ALIGN=Bottom></A><A REL=UP HREF="03_a.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Up]" SRC="../Graphics/Up.gif" ALIGN=Bottom></A><A REL=NEXT HREF="03_ae.htm"><IMG WIDTH=40 HEIGHT=40 ALT="[Next]" SRC="../Graphics/Next.gif" ALIGN=Bottom></A></H1>
<HR>
<H2>
3.1.4 Closures and Lexical Binding</H2> <P>
A <A REL=DEFINITION HREF="26_glo_l.htm#lexical_closure"><I>lexical closure</I></A> is a <A REL=DEFINITION HREF="26_glo_f.htm#function"><I>function</I></A> that can refer to and alter the values of <A REL=DEFINITION HREF="26_glo_l.htm#lexical_binding"><I>lexical bindings</I></A> <I>established</I> by <A REL=DEFINITION HREF="26_glo_b.htm#binding"><I>binding</I></A> <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>forms</I></A> that textually include the function definition. <P>
Consider this code, where <TT>x</TT> is not declared <A REL=DEFINITION HREF="d_specia.htm#special"><B>special</B></A>: <P>
<PRE>
(defun two-funs (x)
(list (function (lambda () x))
(function (lambda (y) (setq x y)))))
(setq funs (two-funs 6))
(funcall (car funs)) =&gt; 6
(funcall (cadr funs) 43) =&gt; 43
(funcall (car funs)) =&gt; 43
</PRE>
</TT> <P>
The <A REL=DEFINITION HREF="s_fn.htm#function"><B>function</B></A> <A REL=DEFINITION HREF="26_glo_s.htm#special_form"><I>special form</I></A> coerces a <A REL=DEFINITION HREF="26_glo_l.htm#lambda_expression"><I>lambda expression</I></A> into a <A REL=DEFINITION HREF="26_glo_c.htm#closure"><I>closure</I></A> in which the <A REL=DEFINITION HREF="26_glo_l.htm#lexical_environment"><I>lexical environment</I></A> in effect when the <A REL=DEFINITION HREF="26_glo_s.htm#special_form"><I>special form</I></A> is evaluated is captured along with the <A REL=DEFINITION HREF="26_glo_l.htm#lambda_expression"><I>lambda expression</I></A>. <P>
The function <TT>two-funs</TT> returns a <A REL=DEFINITION HREF="26_glo_l.htm#list"><I>list</I></A> of two <A REL=DEFINITION HREF="26_glo_f.htm#function"><I>functions</I></A>, each of which refers to the <A REL=DEFINITION HREF="26_glo_b.htm#binding"><I>binding</I></A> of the variable <TT>x</TT> created on entry to the function <TT>two-funs</TT> when it was called. This variable has the value <TT>6</TT> initially, but <A REL=DEFINITION HREF="s_setq.htm#setq"><B>setq</B></A> can alter this <A REL=DEFINITION HREF="26_glo_b.htm#binding"><I>binding</I></A>. The <A REL=DEFINITION HREF="26_glo_l.htm#lexical_closure"><I>lexical closure</I></A> created for the first <A REL=DEFINITION HREF="26_glo_l.htm#lambda_expression"><I>lambda expression</I></A> does not ``snapshot'' the <A REL=DEFINITION HREF="26_glo_v.htm#value"><I>value</I></A> <TT>6</TT> for <TT>x</TT> when the <A REL=DEFINITION HREF="26_glo_c.htm#closure"><I>closure</I></A> is created; rather it captures the <A REL=DEFINITION HREF="26_glo_b.htm#binding"><I>binding</I></A> of <TT>x</TT>. The second <A REL=DEFINITION HREF="26_glo_f.htm#function"><I>function</I></A> can be used to alter the <A REL=DEFINITION HREF="26_glo_v.htm#value"><I>value</I></A> in the same (captured) <A REL=DEFINITION HREF="26_glo_b.htm#binding"><I>binding</I></A> (to <TT>43</TT>, in the example), and this altered variable binding then affects the value returned by the first <A REL=DEFINITION HREF="26_glo_f.htm#function"><I>function</I></A>. <P>
In situations where a <A REL=DEFINITION HREF="26_glo_c.htm#closure"><I>closure</I></A> of a <A REL=DEFINITION HREF="26_glo_l.htm#lambda_expression"><I>lambda expression</I></A> over the same set of <A REL=DEFINITION HREF="26_glo_b.htm#binding"><I>bindings</I></A> may be produced more than once, the various resulting <A REL=DEFINITION HREF="26_glo_c.htm#closure"><I>closures</I></A> may or may not be <A REL=DEFINITION HREF="26_glo_i.htm#identical"><I>identical</I></A>, at the discretion of the <A REL=DEFINITION HREF="26_glo_i.htm#implementation"><I>implementation</I></A>. That is, two <A REL=DEFINITION HREF="26_glo_f.htm#function"><I>functions</I></A> that are behaviorally indistinguishable might or might not be <A REL=DEFINITION HREF="26_glo_i.htm#identical"><I>identical</I></A>. Two <A REL=DEFINITION HREF="26_glo_f.htm#function"><I>functions</I></A> that are behaviorally distinguishable are <A REL=DEFINITION HREF="26_glo_d.htm#distinct"><I>distinct</I></A>. For example: <P>
<PRE>
(let ((x 5) (funs '()))
(dotimes (j 10)
(push #'(lambda (z)
(if (null z) (setq x 0) (+ x z)))
funs))
funs)
</PRE>
</TT> The result of the above <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A> is a <A REL=DEFINITION HREF="26_glo_l.htm#list"><I>list</I></A> of ten <A REL=DEFINITION HREF="26_glo_c.htm#closure"><I>closures</I></A>. Each requires only the <A REL=DEFINITION HREF="26_glo_b.htm#binding"><I>binding</I></A> of <TT>x</TT>. It is the same <A REL=DEFINITION HREF="26_glo_b.htm#binding"><I>binding</I></A> in each case, but the ten <A REL=DEFINITION HREF="26_glo_c.htm#closure"><I>closure</I></A> <A REL=DEFINITION HREF="26_glo_o.htm#object"><I>objects</I></A> might or might not be <A REL=DEFINITION HREF="26_glo_i.htm#identical"><I>identical</I></A>. On the other hand, the result of the <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A> <P>
<PRE>
(let ((funs '()))
(dotimes (j 10)
(let ((x 5))
(push (function (lambda (z)
(if (null z) (setq x 0) (+ x z))))
funs)))
funs)
</PRE>
</TT> is also a <A REL=DEFINITION HREF="26_glo_l.htm#list"><I>list</I></A> of ten <A REL=DEFINITION HREF="26_glo_c.htm#closure"><I>closures</I></A>. However, in this case no two of the <A REL=DEFINITION HREF="26_glo_c.htm#closure"><I>closure</I></A> <A REL=DEFINITION HREF="26_glo_o.htm#object"><I>objects</I></A> can be <A REL=DEFINITION HREF="26_glo_i.htm#identical"><I>identical</I></A> because each <A REL=DEFINITION HREF="26_glo_c.htm#closure"><I>closure</I></A> is closed over a distinct <A REL=DEFINITION HREF="26_glo_b.htm#binding"><I>binding</I></A> of <TT>x</TT>, and these <A REL=DEFINITION HREF="26_glo_b.htm#binding"><I>bindings</I></A> can be behaviorally distinguished because of the use of <A REL=DEFINITION HREF="s_setq.htm#setq"><B>setq</B></A>. <P>
The result of the <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A> <P>
<PRE>
(let ((funs '()))
(dotimes (j 10)
(let ((x 5))
(push (function (lambda (z) (+ x z)))
funs)))
funs)
</PRE>
</TT> is a <A REL=DEFINITION HREF="26_glo_l.htm#list"><I>list</I></A> of ten <A REL=DEFINITION HREF="26_glo_c.htm#closure"><I>closure</I></A> <A REL=DEFINITION HREF="26_glo_o.htm#object"><I>objects</I></A> that might or might not be <A REL=DEFINITION HREF="26_glo_i.htm#identical"><I>identical</I></A>. A different <A REL=DEFINITION HREF="26_glo_b.htm#binding"><I>binding</I></A> of <TT>x</TT> is involved for each <A REL=DEFINITION HREF="26_glo_c.htm#closure"><I>closure</I></A>, but the <A REL=DEFINITION HREF="26_glo_b.htm#binding"><I>bindings</I></A> cannot be distinguished because their values are the <A REL=DEFINITION HREF="26_glo_s.htm#same"><I>same</I></A> and immutable (there being no occurrence of <A REL=DEFINITION HREF="s_setq.htm#setq"><B>setq</B></A> on <TT>x</TT>). A compiler could internally transform the <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A> to <P>
<PRE>
(let ((funs '()))
(dotimes (j 10)
(push (function (lambda (z) (+ 5 z)))
funs))
funs)
</PRE>
</TT> where the <A REL=DEFINITION HREF="26_glo_c.htm#closure"><I>closures</I></A> may be <A REL=DEFINITION HREF="26_glo_i.htm#identical"><I>identical</I></A>. <P>
It is possible that a <A REL=DEFINITION HREF="26_glo_c.htm#closure"><I>closure</I></A> does not close over any variable bindings. In the code fragment <P>
<PRE>
(mapcar (function (lambda (x) (+ x 2))) y)
</PRE>
</TT> the function <TT>(lambda (x) (+ x 2))</TT> contains no references to any outside object. In this case, the same <A REL=DEFINITION HREF="26_glo_c.htm#closure"><I>closure</I></A> might be returned for all evaluations of the <A REL=DEFINITION HREF="s_fn.htm#function"><B>function</B></A> <A REL=DEFINITION HREF="26_glo_f.htm#form"><I>form</I></A>. <P>
<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>