[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: lexical closure bug?
- To: Robert Bruce Findler <robby+@CMU.EDU>
- Subject: Re: lexical closure bug?
- From: kab (Kim Barrett)
- Date: Wed, 20 Oct 93 16:00:07 EST
- Cc: info-mcl@cambridge.apple.com
> (let ((*fun* nil))
> (do ((a (list 'a 'b 'c 'd 'e) (cdr a)))
> ((endp a))
> (push #'(lambda () (format t "~a~%" a)) *fun*))
> (mapcar #'funcall *fun*))
>
> I think that this should print out something like:
>
> (a b c d e)
> (b c d e)
> (c d e)
> (d e)
> (e)
>
> Instead, it prints:
> nil
> nil
> nil
> nil
> nil
>
> Am I missing something here?
The result you are seeing is a result of do being implemented by establishing a
single binding of a and updating it to the next value by side effect on each
iteration. So each of your closures is capturing that same single binding, and
when you invoke the closures the value of the captured binding is nil. If you
want distinct bindings for each iteration, you could change your code to
explicitly establish a new binding within the body of the loop, i.e.
(let ((*fun* nil))
(do ((a (list 'a 'b 'c 'd 'e) (cdr a)))
((endp a))
(let ((a a))
(push #'(lambda () (format t "~a~%" a)) *fun*)))
(mapcar #'funcall *fun*))
A different implementation of do, which used tail recursion instead of
tagbody/go and so established a new binding of a for each iteration would have
produced the result you expected.