is this a portable CL? (rebind)



Hello, All!

suppose i want to collect a list of closures i want to evaluate later:

(loop for obj in objects
collect (lambda () (process obj)))

however, this won't work correctly -- all closures will refer to one
variable OBJ in LOOP code, so with typical LOOP implementation they will all
have last OBJ value.

[3]> (loop for fun in
(loop for obj in '(1 2 3 4 5)
collect (lambda () obj))
collect (funcall fun))

(5 5 5 5 5)

to avoid this behaviour, i rebind variable with LET:

(loop for obj in objects
collect (let ((obj obj))
collect (lambda () (process obj))))

this really helps:

CL-USER> (loop for fun in
(loop for obj in '(1 2 3 4 5)
collect (let ((obj obj)) (lambda () obj)))
collect (funcall fun))
(1 2 3 4 5)

however, i'm not sure that this fix works according to Common Lisp standard.
i think it is, as LET creates new variable binding (i could call it other
name), and each closure points to it's own binding.

however at least in one implemenation (ABCL) in compiled mode it doesn't
work:

CL-USER> (funcall (compile nil (lambda () (loop for fun in
(loop for o in '(1 2 3 4 5)
collect (let ((o2 o)) (lambda () o2)))
collect (funcall fun)))))

(5 5 5 5 5)

while all other implementations i've tested (CLISP, SBCL, ACL, Lispworks)
produce expected output
(1 2 3 4 5), at least with default compiler settings.

ABCL implementation maintainer (Peter Graves) suggests to use backquote to
form a list instead of closure, which i find a bit ugly. he says it's a
question if compiler has to propagate constants.
while i believe my version should be correct according to the semantics
about how bindings and closures work.

i appreciate if somebody can clarify this, pointing to paragraphs of
standard specifying which behaviour is correct.

With best regards, Alex Mizrahi.


.



Relevant Pages

  • Re: is this a portable CL? (rebind)
    ... suppose i want to collect a list of closures i want to evaluate later: ... variable OBJ in LOOP code, so with typical LOOP implementation they will all ... collect (lambda () obj)) ...
    (comp.lang.lisp)
  • Re: is this a portable CL? (rebind)
    ... || variable OBJ in LOOP code, so with typical LOOP implementation they will all ... visible when closures are made. ...
    (comp.lang.lisp)
  • Code Addendum 02 - gforth: OpenGL Graphics Lesson 27
    ... \ s-ndx returns the n-th element address of an array ... \ Returns the address of the nth .pointelement in the *obj struct ... \ Returns the address of the nth .plane[] element in the *obj struct ...
    (comp.lang.forth)
  • Re: Please help, IE window DOM (by focus) automation error
    ... Dim shl As ShellWindows ... Dim obj As InternetExplorer ... (Let me first say for testing I inserted a loop delay in so I could ... trigger the error easier, meaning if it was running full speed then I ...
    (microsoft.public.vb.winapi)
  • Re: reduce redundant code
    ... support a specific interface which could be used to ... Then instead of looping through the whole 'bag', ... I have to loop through the whole bag to see if it's A B or C in order to put ... For Each obj in Bag ...
    (microsoft.public.vb.general.discussion)