From b3d41163d48fc51dc4c94acc6975e6fd890aa0b5 Mon Sep 17 00:00:00 2001 From: angusiguess Date: Tue, 8 Mar 2016 23:09:02 -0400 Subject: [PATCH 1/4] Add sequence to stdlib --- pixie/stdlib.pxi | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/pixie/stdlib.pxi b/pixie/stdlib.pxi index 77b3cede..a529de33 100644 --- a/pixie/stdlib.pxi +++ b/pixie/stdlib.pxi @@ -903,7 +903,7 @@ If further arguments are passed, invokes the method named by symbol, passing the (if (next coll) (recur (next coll)) (first coll)) - + (satisfies? ISeqable coll) (recur (seq coll)))) @@ -2106,7 +2106,7 @@ For more information, see http://clojure.org/special_forms#binding-forms"} val not-found))) ISeq - (-first [this] + (-first [this] (when (not= start stop) start)) (-next [this] @@ -2188,6 +2188,14 @@ For more information, see http://clojure.org/special_forms#binding-forms"} ([pred coll] (filter (complement pred) coll))) +(defn sequence + "Returns a lazy sequence of `data`, optionally transforming it using `xform`. + Given an `eduction`, produces a lazy sequence of it." + ([eduction] + (lazy-seq (cons (first eduction) (sequence (rest eduction))))) + ([xform data] + (sequence (eduction xform data)))) + (defn distinct {:doc "Returns the distinct elements in the collection." :signatures [[] [coll]] @@ -3080,7 +3088,7 @@ ex: (vary-meta x assoc :foo 42)" (deftype Iterate [f x] IReduce (-reduce [self rf init] - (loop [next (f x) + (loop [next (f x) acc (rf init x)] (if (reduced? acc) @acc From d340de4ee39936246a6f026f14e3a4b3ba047bfc Mon Sep 17 00:00:00 2001 From: angusiguess Date: Wed, 9 Mar 2016 10:22:12 -0400 Subject: [PATCH 2/4] Handle the empty case, fix eduction to conform to seqable --- pixie/stdlib.pxi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pixie/stdlib.pxi b/pixie/stdlib.pxi index a529de33..ff070380 100644 --- a/pixie/stdlib.pxi +++ b/pixie/stdlib.pxi @@ -1907,7 +1907,7 @@ not enough elements were present." ISeqable (-seq [self] - (reduce conj self))) + (seq (reduce conj self)))) (defn eduction "Returns a reducible/iterable application of the transducers @@ -2192,7 +2192,7 @@ For more information, see http://clojure.org/special_forms#binding-forms"} "Returns a lazy sequence of `data`, optionally transforming it using `xform`. Given an `eduction`, produces a lazy sequence of it." ([eduction] - (lazy-seq (cons (first eduction) (sequence (rest eduction))))) + (when (seq eduction) (lazy-seq (cons (first eduction) (sequence (rest eduction)))))) ([xform data] (sequence (eduction xform data)))) From 1626fff48d763d86f9c0d5c7b5a1ccff14f7017f Mon Sep 17 00:00:00 2001 From: angusiguess Date: Wed, 9 Mar 2016 10:22:20 -0400 Subject: [PATCH 3/4] Add tests --- tests/pixie/test-sequence.pxi | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 tests/pixie/test-sequence.pxi diff --git a/tests/pixie/test-sequence.pxi b/tests/pixie/test-sequence.pxi new file mode 100644 index 00000000..e8a8e748 --- /dev/null +++ b/tests/pixie/test-sequence.pxi @@ -0,0 +1,23 @@ +(ns pixie.tests.test-sequence + (:require [pixie.test :as t])) + +(t/deftest empty-sequences + (t/assert= '() (take 1 (sequence (map inc) '()))) + (t/assert= '() (take 1 (sequence (map inc) []))) + (t/assert= '() (take 1 (sequence (map inc) #{}))) + (t/assert= '() (take 1 (sequence (map inc) {})))) + +(t/deftest non-empty-sequences + (t/assert= '(1 3) (take 2 (sequence (comp + (filter even?) + (map inc)) (range 3)))) + (t/assert= '(1) (take 1 (sequence (distinct) (repeat 4 1))))) + +(t/deftest early-terminating-sequences + (t/assert= '() (take 5 (sequence (filter (fn [x] false)) (repeat 8 8)))) + (t/assert= '(1 2) (take 3 (sequence (map identity) [1 2]))) + (t/assert= #{[:a 1] [:b 2]} (into #{} (take 3 (sequence (filter (fn [[k v]] + (keyword? k)) {:a 1 + :b 2 + "c" 3 + "d" 4})))))) From c94144b43c3a01f1bf4c4921ddc8e8c6912dc97c Mon Sep 17 00:00:00 2001 From: angusiguess Date: Sun, 13 Mar 2016 20:33:58 -0300 Subject: [PATCH 4/4] Make sequence lazy, make educe seq use sequence --- pixie/stdlib.pxi | 20 +++++++++++++------- tests/pixie/test-sequence.pxi | 23 ----------------------- tests/pixie/tests/test-stdlib.pxi | 22 +++++++++++++++++++++- 3 files changed, 34 insertions(+), 31 deletions(-) delete mode 100644 tests/pixie/test-sequence.pxi diff --git a/pixie/stdlib.pxi b/pixie/stdlib.pxi index ff070380..23a9f7e4 100644 --- a/pixie/stdlib.pxi +++ b/pixie/stdlib.pxi @@ -1907,7 +1907,7 @@ not enough elements were present." ISeqable (-seq [self] - (seq (reduce conj self)))) + (sequence xform coll))) (defn eduction "Returns a reducible/iterable application of the transducers @@ -2189,12 +2189,18 @@ For more information, see http://clojure.org/special_forms#binding-forms"} (filter (complement pred) coll))) (defn sequence - "Returns a lazy sequence of `data`, optionally transforming it using `xform`. - Given an `eduction`, produces a lazy sequence of it." - ([eduction] - (when (seq eduction) (lazy-seq (cons (first eduction) (sequence (rest eduction)))))) - ([xform data] - (sequence (eduction xform data)))) + "Returns a lazy sequence of `data`, optionally transforming it using `xform`" + ([coll] + (if (seq? coll) coll + (or (seq coll) ()))) + ([xform coll] + (let [step (defn step [xform acc xs] + (if-let [s (seq xs)] + (let [next-acc ((xform conj) acc (first s))] + (if (= acc next-acc) (step xform next-acc (next s)) + (concat (drop (count acc) next-acc) (step xform next-acc (next s))))) + nil))] + (lazy-seq (step xform [] coll))))) (defn distinct {:doc "Returns the distinct elements in the collection." diff --git a/tests/pixie/test-sequence.pxi b/tests/pixie/test-sequence.pxi deleted file mode 100644 index e8a8e748..00000000 --- a/tests/pixie/test-sequence.pxi +++ /dev/null @@ -1,23 +0,0 @@ -(ns pixie.tests.test-sequence - (:require [pixie.test :as t])) - -(t/deftest empty-sequences - (t/assert= '() (take 1 (sequence (map inc) '()))) - (t/assert= '() (take 1 (sequence (map inc) []))) - (t/assert= '() (take 1 (sequence (map inc) #{}))) - (t/assert= '() (take 1 (sequence (map inc) {})))) - -(t/deftest non-empty-sequences - (t/assert= '(1 3) (take 2 (sequence (comp - (filter even?) - (map inc)) (range 3)))) - (t/assert= '(1) (take 1 (sequence (distinct) (repeat 4 1))))) - -(t/deftest early-terminating-sequences - (t/assert= '() (take 5 (sequence (filter (fn [x] false)) (repeat 8 8)))) - (t/assert= '(1 2) (take 3 (sequence (map identity) [1 2]))) - (t/assert= #{[:a 1] [:b 2]} (into #{} (take 3 (sequence (filter (fn [[k v]] - (keyword? k)) {:a 1 - :b 2 - "c" 3 - "d" 4})))))) diff --git a/tests/pixie/tests/test-stdlib.pxi b/tests/pixie/tests/test-stdlib.pxi index 12ad9912..8805cd14 100644 --- a/tests/pixie/tests/test-stdlib.pxi +++ b/tests/pixie/tests/test-stdlib.pxi @@ -595,7 +595,7 @@ (seq))) ;; expanding transducer with nils (t/assert= '(1 2 3 nil 4 5 6 nil) - (eduction cat [[1 2 3 nil] [4 5 6 nil]]))) + (seq (eduction cat [[1 2 3 nil] [4 5 6 nil]])))) (t/deftest test-trace (try @@ -767,3 +767,23 @@ (t/assert= (reduce (fn [a v] (reduced "foo")) 0 (iterate inc 1)) "foo") (t/assert= (reduce (fn [a v] (if (< a 10) (+ a v) (reduced a))) 0 (iterate (partial + 2) 1)) 16)) +(t/deftest test-sequence-empty-sequences + (t/assert= '() (take 1 (sequence (map inc) '()))) + (t/assert= '() (take 1 (sequence (map inc) []))) + (t/assert= '() (take 1 (sequence (map inc) #{}))) + (t/assert= '() (take 1 (sequence (map inc) {})))) + +(t/deftest test-sequence-non-empty-sequences + (t/assert= '(1 3) (take 2 (sequence (comp + (filter even?) + (map inc)) (range 3)))) + (t/assert= '(1) (take 1 (sequence (distinct) (repeat 4 1))))) + +(t/deftest test-sequence-early-terminating-sequences + (t/assert= '() (take 5 (sequence (filter (fn [x] false)) (repeat 8 8)))) + (t/assert= '(1 2) (take 3 (sequence (map identity) [1 2]))) + (t/assert= #{[:a 1] [:b 2]} (into #{} (take 3 (sequence (filter (fn [[k v]] + (keyword? k)) {:a 1 + :b 2 + "c" 3 + "d" 4}))))))