Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

support internal reduce at coll, not just seq, level, provide fast de…

…fault for all Iterables
  • Loading branch information...
commit 1f90942690d5395330347cb31fdb3d69cea1ec56 1 parent 4e64fa2
@richhickey richhickey authored
Showing with 64 additions and 5 deletions.
  1. +2 −5 src/clj/clojure/core.clj
  2. +62 −0 src/clj/clojure/core/protocols.clj
View
7 src/clj/clojure/core.clj
@@ -6025,12 +6025,9 @@
items, returns val and f is not called."
{:added "1.0"}
([f coll]
- (if-let [s (seq coll)]
- (reduce f (first s) (next s))
- (f)))
+ (clojure.core.protocols/coll-reduce coll f))
([f val coll]
- (let [s (seq coll)]
- (clojure.core.protocols/internal-reduce s f val))))
+ (clojure.core.protocols/coll-reduce coll f val)))
(extend-protocol clojure.core.protocols/IKVReduce
;;slow path default
View
62 src/clj/clojure/core/protocols.clj
@@ -10,11 +10,73 @@
(set! *warn-on-reflection* true)
+(defprotocol CollReduce
+ "Protocol for collection types that can implement reduce faster than
+ first/next recursion. Called by clojure.core/reduce. Baseline
+ implementation defined in terms of Iterable."
+ (coll-reduce [coll f] [coll f val]))
+
(defprotocol InternalReduce
"Protocol for concrete seq types that can reduce themselves
faster than first/next recursion. Called by clojure.core/reduce."
(internal-reduce [seq f start]))
+(defn- seq-reduce
+ ([coll f]
+ (if-let [s (seq coll)]
+ (internal-reduce (next s) f (first s))
+ (f)))
+ ([coll f val]
+ (let [s (seq coll)]
+ (internal-reduce s f val))))
+
+(extend-protocol CollReduce
+ nil
+ (coll-reduce
+ ([coll f] (f))
+ ([coll f val] val))
+
+ Object
+ (coll-reduce
+ ([coll f] (seq-reduce coll f))
+ ([coll f val] (seq-reduce coll f val)))
+
+ ;;aseqs are iterable, masking internal-reducers
+ clojure.lang.ASeq
+ (coll-reduce
+ ([coll f] (seq-reduce coll f))
+ ([coll f val] (seq-reduce coll f val)))
+
+ ;;for range
+ clojure.lang.LazySeq
+ (coll-reduce
+ ([coll f] (seq-reduce coll f))
+ ([coll f val] (seq-reduce coll f val)))
+
+ ;;vector's chunked seq is faster than its iter
+ clojure.lang.PersistentVector
+ (coll-reduce
+ ([coll f] (seq-reduce coll f))
+ ([coll f val] (seq-reduce coll f val)))
+
+ Iterable
+ (coll-reduce
+ ([coll f]
+ (let [iter (.iterator coll)]
+ (if (.hasNext iter)
+ (loop [ret (.next iter)]
+ (if (.hasNext iter)
+ (recur (f ret (.next iter)))
+ ret))
+ (f))))
+ ([coll f val]
+ (let [iter (.iterator coll)]
+ (loop [ret val]
+ (if (.hasNext iter)
+ (recur (f ret (.next iter)))
+ ret)))))
+ )
+
(extend-protocol InternalReduce
nil
(internal-reduce
Please sign in to comment.
Something went wrong with that request. Please try again.