From 92a6432733e30999b65d7123683a93047fc08d61 Mon Sep 17 00:00:00 2001 From: Jason Jackson Date: Fri, 11 May 2012 16:06:13 -0400 Subject: [PATCH][BUILD] repeat for clojure.core.reducers Signed-off-by: Jason Jackson --- src/clj/clojure/core/reducers.clj | 59 ++++++++++++++++++++++++++++---- test/clojure/test_clojure/reducers.clj | 21 +++++++++++ 2 files changed, 73 insertions(+), 7 deletions(-) diff --git a/src/clj/clojure/core/reducers.clj b/src/clj/clojure/core/reducers.clj index efe6118..b25d2be 100644 --- a/src/clj/clojure/core/reducers.clj +++ b/src/clj/clojure/core/reducers.clj @@ -13,7 +13,8 @@ dependency info." :author "Rich Hickey"} clojure.core.reducers - (:refer-clojure :exclude [reduce map mapcat filter remove take take-while drop flatten]) + (:refer-clojure :exclude [reduce map mapcat filter remove take take-while drop + flatten repeat]) (:require [clojure.walk :as walk])) (alias 'core 'clojure.core) @@ -66,6 +67,15 @@ (defn- fjfork [task] (.fork ^jsr166y.ForkJoinTask task)) (defn- fjjoin [task] (.join ^jsr166y.ForkJoinTask task)))) + +;;;;;;;;;;;;;;;;; Fork/Join Utility Functions ;;;;;;;;;;;;;;;;;;;;;;; + +(defn- fj-invoke-2-fns [fn1 fn2] + (fjinvoke + #(let [t2 (fjtask fn2)] + (fjfork t2) + [(fn1) (fjjoin t2)]))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defn reduce @@ -254,6 +264,45 @@ (f1 ret k v) ret))))))) +(declare repeat) +(defn- fold-repeat + [n x group-size combinef reducef] + (if (<= n group-size) + (reduce reducef (combinef) (repeat n x)) + (let [left (quot n 2) + right (- n left) + fc (fn [n] #(fold-repeat n x group-size combinef reducef))] + (apply combinef (fj-invoke-2-fns (fc left) (fc right)))))) + +(defn repeat + "Returns a reducible collection of infinite!, (or length n if supplied) + sequence of xs. If n is specified, then Foldable." + {:added "1.5"} + ([x] + (reify + clojure.core.protocols/CollReduce + (coll-reduce [this f1] + (clojure.core.protocols/coll-reduce this f1 (f1))) + (coll-reduce [this f1 init] + (loop [ret init] + (if (reduced? ret) + @ret + (recur (f1 ret x))))))) + ([n x] + (reify + clojure.core.protocols/CollReduce + (coll-reduce [this f1] + (clojure.core.protocols/coll-reduce this f1 (f1))) + (coll-reduce [this f1 init] + (loop [ret init, n n] + (cond (reduced? ret) @ret + (<= n 0) ret + :else (recur (f1 ret x) (dec n))))) + + CollFold + (coll-fold [this group-size combinef reducef] + (fold-repeat n x group-size combinef reducef))))) + ;;do not construct this directly, use cat (deftype Cat [cnt left right] clojure.lang.Counted @@ -333,11 +382,7 @@ v1 (subvec v 0 split) v2 (subvec v split (count v)) fc (fn [child] #(foldvec child n combinef reducef))] - (fjinvoke - #(let [f1 (fc v1) - t2 (fjtask (fc v2))] - (fjfork t2) - (combinef (f1) (fjjoin t2))))))) + (apply combinef (fj-invoke-2-fns (fc v1) (fc v2)))))) (extend-protocol CollFold Object @@ -354,4 +399,4 @@ clojure.lang.PersistentHashMap (coll-fold [m n combinef reducef] - (.fold m n combinef reducef fjinvoke fjtask fjfork fjjoin))) + (.fold m n combinef reducef fjinvoke fjtask fjfork fjjoin))) diff --git a/test/clojure/test_clojure/reducers.clj b/test/clojure/test_clojure/reducers.clj index 1123c36..4cb900c 100644 --- a/test/clojure/test_clojure/reducers.clj +++ b/test/clojure/test_clojure/reducers.clj @@ -39,3 +39,24 @@ (defequivtest test-filter [filter r/filter #(into [] %)] [even? odd? #(< 200 %) identity]) + +(deftest test-repeat + ;; equivalent sequences. + (doseq [n [-1 0 1 10 100 1000]] + (is (= (into [] (r/repeat n \x)) + (clojure.core/repeat n \x)))) + + ;; equivalent reductions. + (doseq [n [-1 0 1 10 100 1000]] + (is (= (reduce + (r/repeat n 1)) + (reduce + (clojure.core/repeat n 1))))) + + ;; equivalent folds, group size=default + (doseq [n [-1 0 1 10 100 1000]] + (is (= (r/fold + (r/repeat n 1)) + (reduce + (clojure.core/repeat n 1))))) + + ;; equivalent folds, group size=13 + (doseq [n [-1 0 1 10 100 1000]] + (is (= (r/fold 99 + + (r/repeat n 1)) + (reduce + (clojure.core/repeat n 1)))))) -- 1.7.4.4