Hi Peter,Welcome! The 'with' trick (which confused me when I first saw it aswell) occurs when a loop contains a closure that captures the loopiteration variable:(loop :for i :from 1 :to 3 :collect (lambda () (* i 10)))The question is what value of i each lambda should use when it'scalled. The 'with' trick establishes a new scope with a new bindingfor 'i' inside the loop body and puts the closure inside that scope.Thus, if you do this:(let ((closures (loop :for i :from 1 :to 3 :collect (lambda () (* i 10)))))(loop :for fn :in closures :collect (funcall fn)))... you get '(10 20 30), because each closure remembers the value thati had when it was created. Without the 'with' trick, you'd get '(40 40 40),because the closures all share the loop's original binding for i, andthat held 40 by the time the loop terminated.The fact that it breaks Strict mode, though, means that either PS'simplementation should change, at least to offer the option of notusing it, or drop the trick altogether. I have a feeling the latterwould be simplest. For one thing, Common Lisp, which is PS'stouchstone, doesn't have this scoping behavior. In CCL I get '(40 40 40)for the above expression. And DOTIMES is the same:(let ((list nil))(dotimes (i 3) (push (lambda () (* i 10)) list))(mapcar #'funcall (reverse list)))=> (30 30 30)So this is a case of plus royaliste que le roi that could arguably just beabandoned. If not, though, a special variable for Strict Mode would bea good idea. Vladimir?DanielOn Fri, Mar 1, 2013 at 12:39 PM, Peter Wood <p.r.wood@gmail.com> wrote:
_______________________________________________PeterRegards,What is the point of even having the 'with ({ i : i })' in there ?? I have tried removing the form starting (ps-js:with ... ) and the code which is then generated runs fine and has no 'with', but of course it is probably breaking something else. I don't understand why it's there.Here is an example of some lisp and the js which it generates:(defun compile-loop-bodyIf I 'use strict'; in the start of my scripts, they fail in some of the loops because parenscript is generating a 'with' (which is not allowed in strict mode). There is quite a nice explanation of why it isn't allowed here:HiIt's my first post, so first of all, thanks to everyone who works on parenscript. It is a lifesaver.
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/Strict_mode
It is easy to change my code to use 'do' instead, and for now, that's what I've done, but it's a shame not to be able to use parenscript's very nice loop for writing javascript loops. I haven't looked at parenscript's code before this evening, but I think this is the relevant spot (in src/special-operators.lisp)
...
(aif (sort (remove-duplicates *loop-scope-lexicals-captured*)
#'string< :key #'symbol-name)
`(ps-js:block
(ps-js:with
,(compile-expression
`(create
,@(loop for x in it
collect x
collect (when (member x loop-vars) x))))
,compiled-body))
compiled-body)))
(ps:ps (defun foo ()
(loop for i from 1 to 5
append (loop for j from 1 to 5
collect (list i j)))))
==>
"function foo() {
return (function () {
var append9 = [];
for (var i = 1; i <= 5; i += 1) {
with ({ i : i }) {
^^^^^^^^^^
append9 = append9.concat((function () {
var collect10 = [];
for (var j = 1; j <= 5; j += 1) {
collect10['push']([i, j]);
};
return collect10;
})());
};
};
return append9;
})();
};"
parenscript-devel mailing list
parenscript-devel@common-lisp.net
http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
_______________________________________________
parenscript-devel mailing list
parenscript-devel@common-lisp.net
http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel