From: Vladimir Zolotykh
Subject: closures again
Date: 
Message-ID: <3F192C90.3050600@eurocom.od.ua>
Hi

Let me consider two functions

(defun closure-test-1 ()
   (let (ff)
     (dotimes (n 5)
       (flet ((f () (print n)))
	(push #'f ff)))
     (dolist (f ff) (funcall f))))

which prints: 5 5 5 5 5
and

(defun closure-test-2 ()
   (let (ff)
     (dotimes (n 5)
       (let ((i n))
	(flet ((f () (print i)))
	  (push #'f ff))))
     (dolist (f ff) (funcall f))))

which prints 4 3 2 1 0. Would you mind explaining why ?

-- 
Vladimir Zolotykh

From: Rainer Joswig
Subject: Re: closures again
Date: 
Message-ID: <joswig-CD73D2.14344219072003@news.fu-berlin.de>
In article <················@eurocom.od.ua>,
 Vladimir Zolotykh <······@eurocom.od.ua> wrote:

> Hi
> 
> Let me consider two functions
> 
> (defun closure-test-1 ()
>    (let (ff)
>      (dotimes (n 5)
>        (flet ((f () (print n)))
> 	(push #'f ff)))
>      (dolist (f ff) (funcall f))))
> 
> which prints: 5 5 5 5 5

the closure captures the one binding for n and it
later prints the value for n - whatever n is after
all the iterations.

> and
> 
> (defun closure-test-2 ()
>    (let (ff)
>      (dotimes (n 5)
>        (let ((i n))
> 	(flet ((f () (print i)))
> 	  (push #'f ff))))
>      (dolist (f ff) (funcall f))))
> 
> which prints 4 3 2 1 0. Would you mind explaining why ?

There is a *new* LET binding for "i" in each iteration.
From: Steven M. Haflich
Subject: Re: closures again
Date: 
Message-ID: <3F19906E.4010601@alum.mit.edu>
Rainer Joswig wrote:

>>(defun closure-test-1 ()
>>   (let (ff)
>>     (dotimes (n 5)
>>       (flet ((f () (print n)))
>>	(push #'f ff)))
>>     (dolist (f ff) (funcall f))))
>>
>>which prints: 5 5 5 5 5
> 
> the closure captures the one binding for n and it
> later prints the value for n - whatever n is after
> all the iterations.

Your analysis of the behavior is correct, but the
behavior is actually implementation dependent.  The ANS
description of dotimes explains:

  It is implementation-dependent whether dotimes establishes a
  new binding of var on each iteration or whether it establishes
  a binding for var once at the beginning and then assigns it on
  any subsequent iterations.
From: Frode Vatvedt Fjeld
Subject: Re: closures again
Date: 
Message-ID: <2hd6g6u1un.fsf@vserver.cs.uit.no>
Vladimir Zolotykh <······@eurocom.od.ua> writes:

> (defun closure-test-1 ()
>    (let (ff)
>      (dotimes (n 5)
>        (flet ((f () (print n)))
> 	(push #'f ff)))
>      (dolist (f ff) (funcall f))))

Here you have five closures that close over the same binding, namely
the binding established by dotimes, named n. So when dotimes
eventually sets n to 5, this is visible to all the closures.

Note that two aspects of dotimes' behavior here are
implementation-dependent: The particular value left in n, and the fact
that only one binding is established for n. That is, while your
implementation obviously implements dotimes to the effect of
(let (n) (loop ...)), it is also allowed to implement it as
(loop ... (let (n) ...)), in which case your closure-test-1 would
indeed print 4 3 2 1 0.

> (defun closure-test-2 ()
>    (let (ff)
>      (dotimes (n 5)
>        (let ((i n))
> 	(flet ((f () (print i)))
> 	  (push #'f ff))))
>      (dolist (f ff) (funcall f))))

In this case, each closure unambiguously closes over its own binding,
named i, which are independent of whatever happens to n after the
binding is established.

-- 
Frode Vatvedt Fjeld