From: Gareth McCaughan
Subject: Re: something *very* strange (to *me*). Please help!
Date: 
Message-ID: <867mbu6e6j.fsf@g.pet.cam.ac.uk>
Sam Steingold wrote:

> In CLISP:
> 
> (let ((l (do ((i 0 (1+ i)) r) ((= i 3) (nreverse r))
> 	     (push #'(lambda () i) r))))
>   (mapcar #'funcall l))
> 
> ==> (3 3 3)
> 
> I would expect (0 1 2)
> 
> What is going on?
> How do I get the desired result?
> (declaring i special doesn't change anything)
> Thanks.

The DO loop establishes a single binding for I and side-effects it
each time round the loop, rather than re-binding I. So the I in
the closure you're manufacturing each time is a reference to the
*same* binding, namely the one established by the DO loop.

Here's one way to get the effect you want.

    (let ((l (do ((i 0 (1+ i))
                  (r nil))
                 ((= i 3)
                  (nreverse r))
               (let ((new-i i))
                 (push #'(lambda () new-i) r)) ) ))
      (mapcar #'funcall l))

If you want to confuse your readers, you can replace both occurrences
of NEW-I with I. :-)

-- 
Gareth McCaughan       Dept. of Pure Mathematics & Mathematical Statistics,
·····@dpmms.cam.ac.uk  Cambridge University, England.