Skip to content

Commit 72f2ba9

Browse files
Merge pull request #21 from seancorfield/clarify-transducers
incorporate feedback from slack
2 parents 08393ff + 499184e commit 72f2ba9

File tree

1 file changed

+30
-2
lines changed

1 file changed

+30
-2
lines changed

src/clojure/transducers/what_if.clj

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
(sequence (map *) (range 5) (range 5) (range 5))
3232
(sequence (map vector) (range 5) (range 5) (range 5))
3333

34-
;; How about chaining several transformations together? We can use `eduction`:
34+
;; How about chaining several transformations together? We can use `eduction`
35+
;; (but see the caveats below about `eduction`):
3536

3637
(eduction (filter even?) (map inc) (range 10))
3738

@@ -84,6 +85,18 @@
8485
(transduce (map inc) + 0 (range 5))
8586
(transduce (map inc) * 1 (range 5))
8687

88+
;; The way `(transduce xf f init coll)` works is pretty much like this:
89+
90+
;; ``` clojure
91+
;; (let [rf (xf f)]
92+
;; (rf (reduce rf init coll)))
93+
;; ```
94+
95+
;; Note how `xf` and `f` are combined to create a single "reducing function"
96+
;; (which is a 2-arity function that takes an accumulator and a value), for
97+
;; the `reduce` and then also applied to the result as a 1-arity function,
98+
;; which is what `completing` does for us in the above example.
99+
87100
;; Now let's circle back to chaining transformations, while also controlling
88101
;; the output type. We can use `comp` for this. As a recap, here's our
89102
;; `eduction` from earlier:
@@ -112,7 +125,22 @@
112125
;; Because it is a "reducible", it only does work when it is consumed, so it
113126
;; is "lazy" in that sense, but it is not a lazy sequence. We can get a lazy
114127
;; sequence from a transducer using `sequence`, if we want, or we can rely
115-
;; on `into` and `transduce` etc being eager.
128+
;; on `into` and `transduce` etc being eager. In addition, `eduction` performs
129+
;; the transformations each time it is consumed:
130+
131+
(let [s (eduction (map #(inc (doto % println))) (range 5))]
132+
[(into [] s)
133+
(into [] s)])
134+
135+
;; That will print 0 1 2 3 4 twice, because the `eduction` is consumed twice.
136+
;; Compare that behavior to `sequence`, which produces a lazy sequence and
137+
;; caches its results:
138+
139+
(let [s (sequence (map #(inc (doto % println))) (range 5))]
140+
[(into [] s)
141+
(into [] s)])
142+
143+
;; This will only print 0 1 2 3 4 once.
116144

117145
;; In conclusion,
118146
;; by separating the transformation from the input and the output, we gain

0 commit comments

Comments
 (0)