Skip to content

Commit d2b1b3a

Browse files
Add eduction and completing
The `eduction` function was added, as requested in issue #483. The implementation and the tests were imported and adapted from Clojure's standard library (from [1] and [2], respectively). Since Clojure's implementation uses it, the function `completing` was imported as well (from the same source). As of now, Pixie's stdlib lacks a `sort`/`sort-by` function, one of the tests is disabled (commented out), and another is modified in order to avoid the call to `sort-by`. Sources: Both from Clojure's main repo, fetched at commit `3b98a00`. [1] https://github.com/clojure/clojure/blob/3b98a00e86f961550fb2eaee64e70754e04d1089/src/clj/clojure/core.clj#L7339 [2] https://github.com/clojure/clojure/blob/3b98a00e86f961550fb2eaee64e70754e04d1089/test/clojure/test_clojure/transducers.clj
1 parent ba28b85 commit d2b1b3a

2 files changed

Lines changed: 57 additions & 0 deletions

File tree

pixie/stdlib.pxi

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1884,6 +1884,35 @@ not enough elements were present."
18841884
(when-let [s (seq coll)]
18851885
(reductions f (f init (first s)) (rest s))))))))
18861886

1887+
(defn completing
1888+
"Takes a reducing function f of 2 args and returns a fn suitable for
1889+
transduce by adding an arity-1 signature that calls cf (default -
1890+
identity) on the result argument."
1891+
([f] (completing f identity))
1892+
([f cf]
1893+
(fn
1894+
([] (f))
1895+
([x] (cf x))
1896+
([x y] (f x y)))))
1897+
1898+
(deftype Eduction [xform coll]
1899+
IReduce
1900+
(-reduce [self f init]
1901+
;; NB (completing f) isolates completion of inner rf from outer rf
1902+
(transduce xform (completing f) init coll))
1903+
1904+
ISeqable
1905+
(-seq [self]
1906+
(reduce conj self)))
1907+
1908+
(defn eduction
1909+
"Returns a reducible/iterable application of the transducers
1910+
to the items in coll. Transducers are applied in order as if
1911+
combined with comp. Note that these applications will be
1912+
performed every time reduce/iterator is called."
1913+
[& xforms]
1914+
(->Eduction (apply comp (butlast xforms)) (last xforms)))
1915+
18871916
(defn destructure [binding expr]
18881917
(cond
18891918
(symbol? binding) [binding expr]

tests/pixie/tests/test-stdlib.pxi

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,34 @@
574574
(t/assert= (take 5 (cycle '(1 2))) '(1 2 1 2 1))
575575
(t/assert= (take 3 (cycle [nil])) '(nil nil nil)))
576576

577+
(t/deftest test-eduction
578+
;; one xform
579+
(t/assert= [1 2 3 4 5]
580+
(eduction (map inc) (range 5)))
581+
;; multiple xforms
582+
(t/assert= ["2" "4"]
583+
(eduction (map inc) (filter even?) (map str) (range 5)))
584+
;; materialize at the end
585+
;; TODO: For when sort is implemented
586+
;; (t/assert= [1 1 1 1 2 2 2 3 3 4]
587+
;; (->> (range 5)
588+
;; (eduction (mapcat range) (map inc))
589+
;; sort))
590+
(t/assert= [1 1 2 1 2 3 1 2 3 4]
591+
(vec (->> (range 5)
592+
(eduction (mapcat range) (map inc)))))
593+
(t/assert= {1 4, 2 3, 3 2, 4 1}
594+
(->> (range 5)
595+
(eduction (mapcat range) (map inc))
596+
frequencies))
597+
(t/assert= ["tac" "god" "hsif" "drib" "kravdraa"]
598+
(->> ["cat" "dog" "fish" "bird" "aardvark"]
599+
(eduction (map pixie.string/reverse))
600+
(seq)))
601+
;; expanding transducer with nils
602+
(t/assert= '(1 2 3 nil 4 5 6 nil)
603+
(eduction cat [[1 2 3 nil] [4 5 6 nil]])))
604+
577605
(t/deftest test-trace
578606
(try
579607
(/ 0 0)

0 commit comments

Comments
 (0)