<div>Hi Peter,</div><div><br></div><div>Welcome! The 'with' trick (which confused me when I first saw it as</div><div>well) occurs when a loop contains a closure that captures the loop</div><div>iteration variable:</div>

<div><br></div><div>  (loop :for i :from 1 :to 3 :collect (lambda () (* i 10)))</div><div><br></div><div>The question is what value of i each lambda should use when it's</div><div>called. The 'with' trick establishes a new scope with a new binding</div>

<div>for 'i' inside the loop body and puts the closure inside that scope.</div><div>Thus, if you do this:</div><div><br></div><div>  (let ((closures (loop :for i :from 1 :to 3 :collect (lambda () (* i 10)))))</div>

<div>    (loop :for fn :in closures :collect (funcall fn)))</div><div><br></div><div>... you get '(10 20 30), because each closure remembers the value that</div><div>i had when it was created. Without the 'with' trick, you'd get '(40 40 40),</div>

<div>because the closures all share the loop's original binding for i, and</div><div>that held 40 by the time the loop terminated. </div><div><br></div><div>The fact that it breaks Strict mode, though, means that either PS's</div>

<div>implementation should change, at least to offer the option of not</div><div>using it, or drop the trick altogether. I have a feeling the latter</div><div>would be simplest. For one thing, Common Lisp, which is PS's</div>

<div>touchstone, doesn't have this scoping behavior. In CCL I get '(40 40 40)</div><div>for the above expression. And DOTIMES is the same:</div><div><br></div><div>  (let ((list nil))</div><div>     (dotimes (i 3) (push (lambda () (* i 10)) list))</div>

<div>     (mapcar #'funcall (reverse list)))</div><div><br></div><div>=> (30 30 30)</div><div><br></div><div>So this is a case of plus royaliste que le roi that could arguably just be</div><div>abandoned. If not, though, a special variable for Strict Mode would be</div>

<div>a good idea. Vladimir?</div><div><br></div><div>Daniel</div><div><br></div><br><div class="gmail_quote">On Fri, Mar 1, 2013 at 12:39 PM, Peter Wood <span dir="ltr"><<a href="mailto:p.r.wood@gmail.com" target="_blank">p.r.wood@gmail.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div><div><div><div><div><div>Hi<br><br></div>It's my first post, so first of all, thanks to everyone who works on parenscript.  It is a lifesaver.<br>

<br></div>If 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:<br>


<br><a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/Strict_mode" target="_blank">https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/Strict_mode</a><br>


<br>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)<br>


<br></div>(defun compile-loop-body <br>...<br>(aif (sort (remove-duplicates *loop-scope-lexicals-captured*)<br>               #'string< :key #'symbol-name)<br>         `(ps-js:block<br>              (ps-js:with<br>


                  ,(compile-expression<br>                    `(create<br>                      ,@(loop for x in it<br>                              collect x<br>                              collect (when (member x loop-vars) x))))<br>


                ,compiled-body))<br>         compiled-body)))<br><br></div>Here is an example of some lisp and the js which it generates:<br><br>(ps:ps (defun foo ()<br>                  (loop for i from 1 to 5<br>                     append (loop for j from 1 to 5<br>


                                 collect (list i j))))) <br>==><br>"function foo() {<br>    return (function () {<br>        var append9 = [];<br>        for (var i = 1; i <= 5; i += 1) {<br>            with ({ i : i }) {<br>


        ^^^^^^^^^^<br>                append9 = append9.concat((function () {<br>                    var collect10 = [];<br>                    for (var j = 1; j <= 5; j += 1) {<br>                        collect10['push']([i, j]);<br>


                    };<br>                    return collect10;<br>                })());<br>            };<br>        };<br>        return append9;<br>    })();<br>};"<br><br></div>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.<br>


<br></div>Regards,<br></div>Peter<br></div>
<br>_______________________________________________<br>
parenscript-devel mailing list<br>
<a href="mailto:parenscript-devel@common-lisp.net">parenscript-devel@common-lisp.net</a><br>
<a href="http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel" target="_blank">http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel</a><br>
<br></blockquote></div><br>