I really like these extensions. I read somewhere (maybe CLtL?) that LOOP was supposed to have extension facilities. The original MIT LOOP macro (http://code.google.com/p/mcl/source/browse/library/mit-loop.lisp?r=0c886fce5ddfb32ccf5599cdf6b632d39fa4c68d) which is still used in a lot of implementations has facilities for extension, and CLSQL comes with code that extends the loop macro in several CL implementations (http://items.sjbach.com/loop-extension.lisp).
All this to say that I think these changes would be great in Common Lisp itself (even the MAP...TO, anything to make hash tables easier to use in CL). You should post this to the lisp-pro mailing list (http://lists.common-lisp.net/cgi-bin/mailman/listinfo/pro) as a proposed CDR extension. Vladimir On Wed, Apr 11, 2012 at 8:05 PM, Daniel Gackle <[email protected]> wrote: > I've made the following changes to PS LOOP and pushed them on a branch > called "loop" pending the fixing of the pretty-printer as we discussed > a couple weeks ago. > > These changes capture some idioms that were common in our code. They > deviate from CL's LOOP (I could not bring myself to implement "BEING > THE HASH-KEYS OF") in ways that are appropriate for JS semantics. Since > PS LOOP was not fully compatible with CL's LOOP anyway, this is not much > of a loss. > > (1) Added a FOR..OF clause that iterates through the keys of a JS object. > This translates to JS's "for k in obj" loops and corresponds roughly > to "loop for k being the hash-keys of" in CL. > > (ps (loop :for k :of obj :do (foo k))) > > "for (var k in obj) { > foo(k); > };" > > To bind both key and value, you specify a pair. (This is an icky bit > of syntax but it feels like the least icky option of the ones I'm > aware of.) > > (ps (loop :for (k v) :of obj :do (foo k v))) > > "for (var k in obj) { > var v = obj[k]; > foo(k, v); > };" > > Destructuring works on the value position just like they do everywhere > else, so you can unpack an array. (Note that in this example the key > variable isn't needed so we can put NIL in there.) > > (ps (loop :for (nil (v1 v2)) :of obj :do (foo v1 v2))) > > "for (var _js23095 in obj) { > var _js23096 = obj[_js23095]; > var v1 = _js23096[0]; > var v2 = _js23096[1]; > foo(v1, v2); > };" > > ... or named properties (by using keywords): > > (ps (loop :for (nil (:hello :world)) :of obj :do (foo hello world))) > > "for (var _js23097 in obj) { > var var23099 = obj[_js23097]; > var hello23101 = var23099.hello; > var world23102 = var23099.world; > foo(hello23101, world23102); > };" > > Side note: To get the scoping right for parallel loop clauses is > tricky because LOOP orders things "step test step test" where JS's FOR > does "step step test test", meaning that the second step will be > evaluated even if the first test fails. It got trickier with the > introduction of FOR..OF, so I adopted a simpler implementation that > has some advantages (much tighter generated loop code) but also some > disadvantages: (a) it was a pain to support :INITIALLY clauses so I > dropped them (I'd be surprised if anyone ever used it), and (b) > complex loops sometimes require an extra temporary variable to track > whether the loop is on its first iteration or not. > > (2) There is now a MAP..TO clause that works like COLLECT only instead > of building an array, builds an object mapping keys to values: > > (ps (loop :for str :in strs :map str :to (length str))) > > "(function () { > var _js23109 = strs.length; > var map23110 = { }; > for (var _js23108 = 0; _js23108 < _js23109; _js23108 += 1) { > var str = strs[_js23108]; > map23110[str] = str.length; > }; > return map23110; > })();" > > (3) In FOR..ON, a BY term can now be an integer. For example, you can > say "by 2" instead of "by #'cddr" which makes little sense for JS arrays: > > (ps (loop :for (key val) :on pairs :by 2 :do (foo key val))) > > "for (var _js23094 = pairs; _js23094.length > 0; _js23094 = > _js23094.slice(2)) { > var key = _js23094[0]; > var val = _js23094[1]; > foo(key, val); > };" > > If BY doesn't get a number, it assumes it got a function: > > (ps (loop :for (key val) :on pairs :by blah :do (foo key val))) > > "for (var _js23112 = pairs; _js23112.length > 0; _js23112 = > blah(_js23112)) { > var key = _js23112[0]; > var val = _js23112[1]; > foo(key, val); > };" > > 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
