[Bese-devel] "Miss behavior" :action on loop
szergling
senatorzergling at gmail.com
Wed May 27 04:32:32 UTC 2009
On Sat, May 23, 2009 at 6:41 PM, Fausto Santin <fawxtin at gmail.com> wrote:
> Hi all,
>
> Im updating things from ucw_dev to ucw-core, and simply got 1 hours
> with a little bug bothering me. Right when I was suposed to send a help
> note (this email), I found a solution to the probable bug, but Im
> still sending
> this email to see/know why, and where things happened wrong.
>
> The context: I am updating a simple blog like app, and the main render
> method (that renders the list of posts) is no good at "passing actions".
>
> ;; DO NOT work ok
> (defmethod render-html-body ((self lisdit))
> (<:p (<ucw:a :action (add-post self) "new post"))
> (loop :for post :in (lisdit-posts self)
> :do
> (<:div :id "lisdit-post"
> (render post)
> "post: " (<:as-html (lisdit-post-id post))
> (<ucw:a :action (remove-post (lisdit-post-id post) self) "remove
> it")))) ; XXX here
>
Ah hah, a very common misconception for newbies. In case it's still
not clear enough, loop is doing something like this (pseudo-code only
for illustration)
(let ((post ...))
(loop
(setf post (some-element-of (lisdit-posts self)))
...body...))
All closures (or UCW actions) in body will share the same binding to
post. mapcar uses a different binding time, that's why it worked. To
solve your issue, you just need to rebind post.
(defmethod render-html-body ((self lisdit))
(<:p (<ucw:a :action (add-post self) "new post"))
(loop :for post :in (lisdit-posts self)
:do
;; New binding here, optionally, use a different name
(let ((post post))
(<:div :id "lisdit-post"
(render post)
"post: " (<:as-html (lisdit-post-id post))
(<ucw:a :action (remove-post (lisdit-post-id post) self)
"remove it")))))
This is untested (I don't have UCW handy at the moment), but I hope it
is still useful.
Theam Yong Chew
More information about the bese-devel
mailing list