diff options
author | Rich Hickey <richhickey@gmail.com> | 2008-03-30 18:35:49 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2008-03-30 18:35:49 +0000 |
commit | 399b5d348f906c8993909d6cdcedb034ba70bfa0 (patch) | |
tree | 77ab39e9ee2e4a094c6d5a3775a1074a0d17def7 /src | |
parent | b8b832221bd4d9be2af471b4e9d2635157d08d6a (diff) |
new 'for' syntax, now supports an optional filter per sequence, with either filter (:when) or short-circuit (:while) logic
Diffstat (limited to 'src')
-rw-r--r-- | src/boot.clj | 70 |
1 files changed, 41 insertions, 29 deletions
diff --git a/src/boot.clj b/src/boot.clj index e26a0947..67aa919c 100644 --- a/src/boot.clj +++ b/src/boot.clj @@ -1883,7 +1883,7 @@ not-every? (comp not every?)) (symbol? b) (-> bvec (conj b) (conj v)) (vector? b) (pvec bvec b v) (map? b) (pmap bvec b v) - :else (throw (new Exception "Unsupported binding form"))))) + :else (throw (new Exception (str "Unsupported binding form: " b)))))) process-entry (fn [bvec b] (pb bvec (key b) (val b)))] (if (every? symbol? (keys bmap)) bindings @@ -1930,30 +1930,6 @@ not-every? (comp not every?)) (lazy-cat ~@colls)))] (iter# ~coll)))) -(defmacro for - "List comprehension. Takes one or more - binding-form/collection-expr pairs, an optional filtering - (where) expression, and yields a lazy sequence of evaluations of - expr. Collections are iterated in a nested fashion, rightmost - fastest, and nested coll-exprs can refer to bindings created in - prior binding-forms." - ([seq-expr expr] (list `for seq-expr `true expr)) - ([seq-exprs filter-expr expr] - (let [emit (fn emit [ses] - (let [x (key (first ses)) xs (val (first ses)) - giter (gensym "iter__") gxs (gensym "s__")] - `(fn ~giter [~gxs] - (when-first ~x ~gxs - ~(if (rest ses) - `(let [iterys# ~(emit (rest ses))] - (lazy-cat (iterys# ~(val (second ses))) - (~giter (rest ~gxs)))) - `(if ~filter-expr - (lazy-cons ~expr (~giter (rest ~gxs))) - (recur (rest ~gxs))))))))] - `(let [iter# ~(emit (seq (apply array-map seq-exprs)))] - (iter# ~(second seq-exprs)))))) - ;redefine fn with destructuring (defmacro fn "(fn name? [params* ] exprs*) @@ -1992,6 +1968,41 @@ not-every? (comp not every?)) (cons 'fn* new-sigs)) *macro-meta*))) +(defmacro for + "List comprehension. Takes a vector of one or more + binding-form/collection-expr pairs, each followed by an optional filtering + :when/:while expression (:when test or :while test), and yields a + lazy sequence of evaluations of expr. Collections are iterated in a + nested fashion, rightmost fastest, and nested coll-exprs can refer to + bindings created in prior binding-forms. + + (take 100 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))" + ([seq-exprs expr] + (let [pargs (fn [xs] + (loop [ret [] + [b e & [w f & wr :as r] :as xs] (seq xs)] + (if xs + (cond + (= w :when) (recur (conj ret {:b b :e e :f f :w :when}) wr) + (= w :while) (recur (conj ret {:b b :e e :f f :w :while}) wr) + :else (recur (conj ret {:b b :e e :f true :w :while}) r)) + (seq ret)))) + emit (fn emit [[{b :b f :f w :w} & [{ys :e} :as rses]]] + (let [giter (gensym "iter__") gxs (gensym "s__")] + `(fn ~giter [~gxs] + (when-first ~b ~gxs + (if ~f + ~(if rses + `(let [iterys# ~(emit rses)] + (lazy-cat (iterys# ~ys) + (~giter (rest ~gxs)))) + `(lazy-cons ~expr (~giter (rest ~gxs)))) + ~(if (= w :when) + `(recur (rest ~gxs)) + nil))))))] + `(let [iter# ~(emit (pargs seq-exprs))] + (iter# ~(second seq-exprs)))))) + (defmacro comment "Ignores body, yields nil" [& body]) @@ -2132,10 +2143,11 @@ not-every? (comp not every?)) contains a match for re-string" [re-string] (let [re (re-pattern re-string)] - (dorun (for [ns (all-ns) v (sort-by (comp :name meta) (vals (ns-interns ns)))] - (and (:doc ^v) - (or (re-find (re-matcher re (:doc ^v))) - (re-find (re-matcher re (str (:name ^v)))))) + (dorun (for [ns (all-ns) + v (sort-by (comp :name meta) (vals (ns-interns ns))) + :when (and (:doc ^v) + (or (re-find (re-matcher re (:doc ^v))) + (re-find (re-matcher re (str (:name ^v))))))] (print-doc v))))) (defmacro doc |