Permalink
Browse files

CLJS-2445: Reducible sequence generators

  • Loading branch information...
mfikes authored and swannodette committed Dec 22, 2017
1 parent 2448716 commit 457faf89757b249345fa37bb33961dde6de9a7c6
Showing with 480 additions and 11 deletions.
  1. +28 −1 benchmark/cljs/benchmark_runner.cljs
  2. +230 −9 src/main/cljs/cljs/core.cljs
  3. +222 −1 src/test/cljs/cljs/collections_test.cljs
@@ -421,4 +421,31 @@
(simple-benchmark [x js/Infinity] (pr-str x) 1000000)
(simple-benchmark [x js/-Infinity] (pr-str x) 1000000)
(simple-benchmark [x (js-obj)] (pr-str x) 1000000)
(println)
(println "\n")
(println ";; cycle")
(simple-benchmark [] (doall (take 1000 (cycle [1 2 3]))) 1000)
(simple-benchmark [] (into [] (take 1000) (cycle [1 2 3])) 1000)
(simple-benchmark [] (reduce + (take 64 (cycle [1 2 3]))) 10000)
(simple-benchmark [] (transduce (take 64) + (cycle [1 2 3])) 10000)
(println "\n")
(println ";; repeat")
(simple-benchmark [] (doall (take 1000 (repeat 1))) 1000)
(simple-benchmark [] (into [] (take 1000) (repeat 1)) 1000)
(simple-benchmark [] (doall (repeat 1000 1)) 1000)
(simple-benchmark [] (into [] (repeat 1000 1)) 1000)
(simple-benchmark [] (reduce + 0 (repeat 1000 1)) 1000)
(simple-benchmark [] (into [] (take 1000) (repeat 1)) 1000)
(simple-benchmark [] (reduce + (take 64 (repeat 1))) 10000)
(simple-benchmark [] (transduce (take 64) + (repeat 1)) 10000)
(simple-benchmark [] (reduce + (take 64 (repeat 48 1))) 10000)
(simple-benchmark [] (transduce (take 64) + (repeat 48 1)) 10000)
(println "\n")
(println ";; iterate")
(simple-benchmark [] (doall (take 1000 (iterate inc 0))) 1000)
(simple-benchmark [] (into [] (take 1000) (iterate inc 0)) 1000)
(simple-benchmark [] (reduce + (take 64 (iterate inc 0))) 10000)
(simple-benchmark [] (transduce (take 64) + (iterate inc 0)) 10000)
(println)
@@ -1897,7 +1897,7 @@ reduces them without incurring seq initialization"
"Returns the nth rest of coll, coll when n is 0."
[coll n]
(loop [n n xs coll]
(if (and (pos? n) (seq xs))
(if-let [xs (and (pos? n) (seq xs))]
(recur (dec n) (rest xs))
xs)))
@@ -4775,21 +4775,175 @@ reduces them without incurring seq initialization"
s)))]
(lazy-seq (step pred coll)))))
(deftype Cycle [meta all prev ^:mutable current ^:mutable _next]
Object
(toString [coll]
(pr-str* coll))
(currentval [coll]
(when-not ^seq current
(if-let [c (next prev)]
(set! current c)
(set! current all)))
current)
IPending
(-realized? [coll]
(some? current))
IWithMeta
(-with-meta [coll meta] (Cycle. meta all prev current _next))
IMeta
(-meta [coll] meta)
ISeq
(-first [coll]
(first (.currentval coll)))
(-rest [coll]
(when (nil? _next)
(set! _next (Cycle. nil all (.currentval coll) nil nil)))
_next)
INext
(-next [coll]
(-rest coll))
ICollection
(-conj [coll o] (cons o coll))
IEmptyableCollection
(-empty [coll] (-with-meta (.-EMPTY List) meta))
ISequential
ISeqable
(-seq [coll] coll)
IReduce
(-reduce [coll f]
(loop [s (.currentval coll) ret (first s)]
(let [s (or (next s) all)
ret (f ret (first s))]
(if (reduced? ret)
@ret
(recur s ret)))))
(-reduce [coll f start]
(loop [s (.currentval coll) ret start]
(let [ret (f ret (first s))]
(if (reduced? ret)
@ret
(recur (or (next s) all) ret))))))
(defn cycle
"Returns a lazy (infinite!) sequence of repetitions of the items in coll."
[coll] (lazy-seq
(when-let [s (seq coll)]
(concat s (cycle s)))))
[coll] (if-let [vals (seq coll)]
(Cycle. nil vals nil vals nil)
(.-EMPTY List)))
(defn split-at
"Returns a vector of [(take n coll) (drop n coll)]"
[n coll]
[(take n coll) (drop n coll)])
(deftype Repeat [meta count val ^:mutable next ^:mutable __hash]
Object
(toString [coll]
(pr-str* coll))
(equiv [this other]
(-equiv this other))
(indexOf [coll x]
(-indexOf coll x 0))
(indexOf [coll x start]
(-indexOf coll x start))
(lastIndexOf [coll x]
(-lastIndexOf coll x count))
(lastIndexOf [coll x start]
(-lastIndexOf coll x start))
IPending
(-realized? [coll] false)
IWithMeta
(-with-meta [coll meta] (Repeat. meta count val next nil))
IMeta
(-meta [coll] meta)
ISeq
(-first [coll]
val)
(-rest [coll]
(if (nil? next)
(if (> count 1)
(do
(set! next (Repeat. nil (dec count) val nil nil))
next)
(if (== -1 count)
coll
()))
next))
INext
(-next [coll]
(if (nil? next)
(if (> count 1)
(do
(set! next (Repeat. nil (dec count) val nil nil))
next)
(if (== -1 count)
coll
nil))
next))
ICollection
(-conj [coll o] (cons o coll))
IEmptyableCollection
(-empty [coll] (-with-meta (.-EMPTY List) meta))
IHash
(-hash [coll] (caching-hash coll hash-ordered-coll __hash))
ISequential
ISeqable
(-seq [coll] coll)
IEquiv
(-equiv [coll other] (equiv-sequential coll other))
IReduce
(-reduce [coll f]
(if (== count -1)
(loop [ret (f val val)]
(if (reduced? ret)
@ret
(recur (f ret val))))
(loop [i 1 ret val]
(if (< i count)
(let [ret (f ret val)]
(if (reduced? ret)
@ret
(recur (inc i) ret)))
ret))))
(-reduce [coll f start]
(if (== count -1)
(loop [ret (f start val)]
(if (reduced? ret)
@ret
(recur (f ret val))))
(loop [i 0 ret start]
(if (< i count)
(let [ret (f ret val)]
(if (reduced? ret)
@ret
(recur (inc i) ret)))
ret)))))
(defn repeat
"Returns a lazy (infinite!, or length n if supplied) sequence of xs."
([x] (lazy-seq (cons x (repeat x))))
([n x] (take n (repeat x))))
([x] (Repeat. nil -1 x nil nil))
([n x] (if (pos? n)
(Repeat. nil n x nil nil)
(.-EMPTY List))))
(defn replicate
"DEPRECATED: Use 'repeat' instead.
@@ -4803,10 +4957,68 @@ reduces them without incurring seq initialization"
([f] (lazy-seq (cons (f) (repeatedly f))))
([n f] (take n (repeatedly f))))
(def ^:private UNREALIZED-SEED #js {})
(deftype Iterate [meta f prev-seed ^:mutable seed ^:mutable next]
Object
(toString [coll]
(pr-str* coll))
IPending
(-realized? [coll]
(not (identical? seed UNREALIZED-SEED)))
IWithMeta
(-with-meta [coll meta] (Iterate. meta f prev-seed seed next))
IMeta
(-meta [coll] meta)
ISeq
(-first [coll]
(when (identical? UNREALIZED-SEED seed)
(set! seed (f prev-seed)))
seed)
(-rest [coll]
(when (nil? next)
(set! next (Iterate. nil f (-first coll) UNREALIZED-SEED nil)))
next)
INext
(-next [coll]
(-rest coll))
ICollection
(-conj [coll o] (cons o coll))
IEmptyableCollection
(-empty [coll] (-with-meta (.-EMPTY List) meta))
ISequential
ISeqable
(-seq [coll] coll)
IReduce
(-reduce [coll rf]
(let [first (-first coll)
v (f first)]
(loop [ret (rf first v) v v]
(if (reduced? ret)
@ret
(let [v (f v)]
(recur (rf ret v) v))))))
(-reduce [coll rf start]
(let [v (-first coll)]
(loop [ret (rf start v) v v]
(if (reduced? ret)
@ret
(let [v (f v)]
(recur (rf ret v) v)))))))
(defn iterate
"Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects"
{:added "1.0"}
[f x] (cons x (lazy-seq (iterate f (f x)))))
[f x] (Iterate. nil f nil x nil))
(defn interleave
"Returns a lazy seq of the first item in each coll, then the second etc."
@@ -9507,8 +9719,8 @@ reduces them without incurring seq initialization"
be used to force any effects. Walks through the successive nexts of
the seq, does not retain the head and returns nil."
([coll]
(when (seq coll)
(recur (next coll))))
(when-let [s (seq coll)]
(recur (next s))))
([n coll]
(when (and (seq coll) (pos? n))
(recur (dec n) (next coll)))))
@@ -9960,6 +10172,15 @@ reduces them without incurring seq initialization"
Range
(-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "(" " " ")" opts coll))
Cycle
(-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "(" " " ")" opts coll))
Repeat
(-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "(" " " ")" opts coll))
Iterate
(-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "(" " " ")" opts coll))
ES6IteratorSeq
(-pr-writer [coll writer opts] (pr-sequential-writer writer pr-writer "(" " " ")" opts coll))
Oops, something went wrong.

0 comments on commit 457faf8

Please sign in to comment.