diff options
author | Chouser <chouser@n01se.net> | 2009-08-23 21:36:41 -0400 |
---|---|---|
committer | Chouser <chouser@n01se.net> | 2009-08-24 16:17:40 -0400 |
commit | 14316ae2110a779ffc8ac9c3da3f1c41852c4289 (patch) | |
tree | 11d06ae269bf989cdbe08100a142199c58745223 /src | |
parent | 4af9fcf218c04db9b38fb4ce35591f1ff17a4f15 (diff) |
Add support for chunked seqs to 'for'. Refs #1
Diffstat (limited to 'src')
-rw-r--r-- | src/clj/clojure/core.clj | 49 |
1 files changed, 43 insertions, 6 deletions
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index 2a17e788..992989e5 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -2858,7 +2858,7 @@ binding-forms. Supported modifiers are: :let [binding-form expr ...], :while test, :when test. - (take 100 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))" + (take 100 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))" [seq-exprs body-expr] (assert-args for (vector? seq-exprs) "a vector for its binding" @@ -2890,11 +2890,48 @@ (recur (rest ~gxs)))) :else `(cons ~body-expr (~giter (rest ~gxs)))))] - `(fn ~giter [~gxs] - (lazy-seq - (loop [~gxs ~gxs] - (when-first [~bind ~gxs] - ~(do-mod mod-pairs)))))))] + (if next-groups + #_"not the inner-most loop" + `(fn ~giter [~gxs] + (lazy-seq + (loop [~gxs ~gxs] + (when-first [~bind ~gxs] + ~(do-mod mod-pairs))))) + #_"inner-most loop" + (let [gi (gensym "i__") + gb (gensym "b__") + do-cmod (fn do-cmod [[[k v :as pair] & etc]] + (cond + (= k :let) `(let ~v ~(do-cmod etc)) + (= k :while) `(when ~v ~(do-cmod etc)) + (= k :when) `(if ~v + ~(do-cmod etc) + (recur + (unchecked-inc ~gi))) + (keyword? k) + (err "Invalid 'for' keyword " k) + :else + `(do (chunk-append ~gb ~body-expr) + (recur (unchecked-inc ~gi)))))] + `(fn ~giter [~gxs] + (lazy-seq + (loop [~gxs ~gxs] + (when-let [~gxs (seq ~gxs)] + (if (chunked-seq? ~gxs) + (let [c# (chunk-first ~gxs) + size# (int (count c#)) + ~gb (chunk-buffer size#)] + (if (loop [~gi (int 0)] + (if (< ~gi size#) + (let [~bind (.nth c# ~gi)] + ~(do-cmod mod-pairs)) + true)) + (chunk-cons + (chunk ~gb) + (~giter (chunk-rest ~gxs))) + (chunk-cons (chunk ~gb) nil))) + (let [~bind (first ~gxs)] + ~(do-mod mod-pairs)))))))))))] `(let [iter# ~(emit-bind (to-groups seq-exprs))] (iter# ~(second seq-exprs))))) |