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

scoping...



> (apply #'add-menu-items foobar
>   (let ((activities #(A B C))
>         (items nil)
>         activity)
>     ;(declare (<WHAT GOES HERE?!!!> activity)
>     (dotimes (i (length activities) (nreverse items))
>       (setq activity (aref activities i))
>       (push
>         (make-instance 'menu-item
>           :menu-item-title (string activity)
>           :menu-item-action
>           #'(lambda ()
>               (print activity)))
>         items))))
> 
> #|
> 
> This results in a list of menu-items, each with the correct title, but the
> functions all affect the LAST activity, rather than the ith.  ie, All of
> the menu-items print C.
> 
> I understand that the variable activity is incorrectly scoped, but what do
> I do to fix it?
> 
> |#

Move the binding of activity inside the loop, i.e.

(apply #'add-menu-items foobar
  (let ((activities #(A B C))
        (items nil))
    (dotimes (i (length activities) (nreverse items))
      (let ((activity (aref activities i)))
        ;(declare (<type of entries in activities> activity))
        (push
          (make-instance 'menu-item
            :menu-item-title (string activity)
            :menu-item-action
            #'(lambda ()
                (print activity)))
          items)))))

This way, each of the menu item actions is closing over a distinct binding, 
rather than having them all closing over the same binding that got setq'ed 
several times.