Confused about closures and scoping rules
Jakub Hegenbart
kyosuke at kimagure.cz
Thu Nov 8 02:02:51 EST 2007
On Wed, 07 Nov 2007 01:37:00 +0100, Chris Mellon <arkanes at gmail.com> wrote:
> Are there languages where closures *don't* behave like this? A closure
> that used a copy of the state rather than the actual state itself
> doesn't seem as useful. For references sake, JavaScript (the only
> language that a) has closures and b) I have a handy way to test with)
> does the same thing.
The results in an equivalent code might depend on the semantics of the
looping construct used. For example, take Scheme (I'm using Gauche Scheme):
(define (outer-1 nmax)
(let ((aa '()))
(dotimes (n nmax)
(push! aa (lambda (y) (list "y:" y "n:" n))))
aa))
(define (outer-2 nmax)
(let ((aa '())
(n 0))
(until (= n nmax)
(push! aa (lambda (y) (list "y:" y "n:" n)))
(set! n (+ n 1)))
aa))
(print (map (lambda (f) (f 1)) (outer-1 5)))
(print (map (lambda (f) (f 1)) (outer-2 5)))
$ gosh closures.scm
((y: 1 n: 4) (y: 1 n: 3) (y: 1 n: 2) (y: 1 n: 1) (y: 1 n: 0))
((y: 1 n: 5) (y: 1 n: 5) (y: 1 n: 5) (y: 1 n: 5) (y: 1 n: 5))
In outer-1, the (dotimes ...) form expands into (do ...). R5RS defines
that a (do ...) loop is expected to _rebound_ all of its state variables
(here it is only n) in each iteration step. This means that each closure
created captures a different binding. Whereas in outer-2, I am updating
the binding destructively, so the value changes in the environment of
all the closures that have been already stored. Python seems to do the
latter. (I am not a pythonist right now, but I am learning... :))
Regards,
Jakub
More information about the Python-list
mailing list