[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: something *very* strange (to *me*).



Sam Steingold <sshteingold@cctrading.com> writes:
> 
>      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?

This is a very unfortunate pitfall in Common Lisp. The #'(lambda () i)
captures the "binding" of the variable i, not its value - so that you
can setf i from within the function. Therefore

      (let ((i 0)) (push #'(lambda () ...) l))
      (let ((i 1)) (push #'(lambda () ...) l))

and

      (let ((i 0)) (push #'(lambda () ...) l)
        (setq i 1) (push #'(lambda () ...) l))

are different: in the first case, the two functions operate on separate
i_s, in the second they can interact through the variable i.

Unfortunately, Common Lisp's `do' macro chooses the second alternative.
(For efficiency reasons, I assume.)

>      How do I get the desired result?

Instead of
                 #'(lambda () i)
you write
                 (let ((i i)) #'(lambda () i))

Looks stupid, but does the trick.


                         Bruno