Two examples followed by patch. Note that I haven't added any functions for #'cdr, #'cddr etc. (it's arguable whether those belong in PS proper, since the mapping of Lisp lists to JS arrays is only partly satisfactory), so if you want to write stuff like "(ps (loop for (a b) on list by #'cddr))", you can, but you have to define your own #'cddr.<br>
<br>Dan<br><br>(ps (loop for (a b) on y do (blah a b)))<br>=><br>"for (var _js46 = y; !(_js46 == null || _js46.length == 0); _js46 = _js46.slice(1)) {<br> var a = _js46[0];<br> var b = _js46[1];<br> blah(a, b);<br>
};"<br><br>(ps (loop for (a b . c) on list by somefn do (blah a b c)))<br>=><br>"for (var _js48 = list; !(_js48 == null || _js48.length == 0); _js48 = somefn(_js48)) {<br> var a = _js48[0];<br> var b = _js48[1];<br>
var c = _js48.length > 2 ? slice(_js48, 2) : null;<br> blah(a, b, c);<br>};"<br><br>From 4122fd1552b35f9bc46d723cf1651fdc8cf20748 Mon Sep 17 00:00:00 2001<br>From: Daniel Gackle <<a href="mailto:danielgackle@gmail.com">danielgackle@gmail.com</a>><br>
Date: Fri, 10 Jul 2009 19:17:39 -0600<br>Subject: [PATCH 2/2] PS LOOP now supports ON.<br><br>---<br> src/lib/ps-loop.lisp | 22 +++++++++++++++++++---<br> 1 files changed, 19 insertions(+), 3 deletions(-)<br><br>diff --git a/src/lib/ps-loop.lisp b/src/lib/ps-loop.lisp<br>
index 0e20c9c..c7334fa 100644<br>--- a/src/lib/ps-loop.lisp<br>+++ b/src/lib/ps-loop.lisp<br>@@ -2,12 +2,13 @@<br> <br> (defun complex-js-expr? (expr)<br> (if (symbolp expr)<br>- (find #\. (symbol-name expr))<br>+ (or (find #\. (symbol-name expr))<br>
+ (not (eq (ps-macroexpand expr) expr)))<br> (consp expr)))<br> <br> (defvar *loop-keywords*<br> '(:for :do :when :unless :initially :finally :first-time :last-time :while :until<br>- :from :to :below :downto :above :by :in :across :index := :then :sum :collect<br>
+ :from :to :below :downto :above :by :in :across :on :index := :then :sum :collect<br> :count :minimize :maximize :into))<br> <br> (defun normalize-loop-keywords (args)<br>@@ -18,6 +19,11 @@<br> x))<br> args))<br>
<br>+(defun reduce-function-symbol (sym)<br>+ (if (and (consp sym) (eq 'function (first sym)))<br>+ (second sym)<br>+ sym))<br>+<br> (defun parse-ps-loop (terms)<br> (let (prologue<br> init-step-forms end-test-forms<br>
@@ -115,6 +121,15 @@<br> (setf terms (append equiv terms))<br> (clause)<br> (clause))))<br>+ (for-on (var)<br>+ (with-local-var (arr (consume))<br>
+ (push `(or (null ,var) (= (length ,var) 0)) end-test-forms)<br>+ (let* ((by (aif (consume-if :by)<br>+ `(,(reduce-function-symbol it) ,var)<br>+ `((@ ,var :slice) 1)))<br>
+ (equiv `(:for ,var := ,arr :then ,by)))<br>+ (setf terms (append equiv terms))<br>+ (clause))))<br> (for-clause ()<br> (let* ((place (consume))<br>
(var (when (atom place) place))<br>@@ -122,13 +137,14 @@<br> (term (consume-atom)))<br> (when varlist<br> (when (eq term :from)<br>
- (err "an atom after FROM" varlist))<br>
+ (err "an atom after FOR" varlist))<br> (setf var (ps-gensym))<br> (push (list varlist var) destructurings))<br> (case term<br>
(:from (for-from var))<br> (:= (for-= var))<br> ((:in :across) (for-in var))<br>+ (:on (for-on var))<br> (otherwise (error "FOR ~s ~s is not valid in PS-LOOP." var term)))))<br>
(clause ()<br> (let ((term (consume-atom)))<br>-- <br>1.6.1<br><br><br>