Thanks. I noticed the same thing about CL, but wasn't clear on the principle. Now I think I understand. The salient question is: was the variable declared inside the loop? If it was, there's an implicit request to get a new binding each time the loop executes. If it wasn't, all closures over the variable will share the same binding.
On Fri, Apr 6, 2012 at 5:52 PM, Vladimir Sedach <[email protected]> wrote: > That's the correct behavior because you're closing over the same > binding of i in all iterations. This equivalent CL code: > > (let ((foo (make-array 3)) > (i 0)) > (loop while (< i 3) do > (setf (aref foo i) (lambda () i)) > (incf i)) > (funcall #'princ (funcall (aref foo 0))) > (funcall #'princ (funcall (aref foo 1))) > (funcall #'princ (funcall (aref foo 2)))) > > Also does 3 3 3 > > Vladimir > > On Thu, Apr 5, 2012 at 7:20 PM, Daniel Gackle <[email protected]> > wrote: > > When a closure is created inside a loop, PS wraps the closed-over > > variables using a JS WITH statement to ensure that each closure will get > > the values that existed at the time it was created. Here's an example > > from Vladimir's email to the list from Jan 30, 2011: > > > > (let ((foo (make-array 3))) > > (dotimes (i 3) > > (setf (aref foo i) (lambda () i))) > > (funcall (@ console log) (funcall (aref foo 0))) > > (funcall (@ console log) (funcall (aref foo 1))) > > (funcall (@ console log) (funcall (aref foo 2)))) > > > > This correctly prints 0,1,2 to the console. If PS didn't do this extra > > work and relied on JS scoping, the output would be 3,3,3 which is > > obviously (or at least arguably) incorrect. > > > > But this doesn't happen for variables declared prior to the loop form. > > Here is the above example written to use WHILE rather than DOTIMES: > > > > (let ((foo (make-array 3)) > > (i 0)) > > (while (< i 3) > > (setf (aref foo i) (lambda () i)) > > (incf i)) > > (funcall (@ console log) (funcall (aref foo 0))) > > (funcall (@ console log) (funcall (aref foo 1))) > > (funcall (@ console log) (funcall (aref foo 2)))) > > > > It prints 3,3,3. Of course, probably no one would use WHILE to write > > this particular loop, but it's easy to see how one might run in to the > > problem. In particular, the PS LOOP macro generates WHILE forms for > > many standard kinds of loop. That is how I ran across this issue: I > > have a LOOP form that builds a table of closures for asynchronous > > callback in a Node.js program and by the time these closures are > > called back, they no longer have their expected data - for exactly the > > same reason as the above example prints 3,3,3. > > > > My first question is: is this a bug? That is, if it's incorrect for the > > first loop to print 3,3,3, is it also incorrect for the second loop to > > do so? > > > > Daniel > > > > > > _______________________________________________ > > parenscript-devel mailing list > > [email protected] > > http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel > > > > _______________________________________________ > parenscript-devel mailing list > [email protected] > http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel >
_______________________________________________ parenscript-devel mailing list [email protected] http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
