I am writing a custom transducer as an exercise, but I am surprised to see that its 0-arity init function is not called.
Why?
Is it related to which aggregation function I am using? If yes, which ones would call the init function and why others are not?
(defn inc-xf [xf]
"inc-xf should be equivalent to (map inc)"
(fn
;; init
([]
(println "init") ;; <- this is not called (???)
(xf))
;; step
([result input]
(println "step" result input)
(xf result (inc input)))
;; completion
([result]
(println "completion" result)
(xf result))))
(transduce inc-xf
+
100
[5 5 5])
If you look at the implementation of transduce
you can see what happens.
(defn transduce
;; To get the init value, (f) is used instead of ((xform f))
([xform f coll] (transduce xform f (f) coll))
([xform f init coll]
,,,))
Why, however, is more difficult to answer.
Transducers implementing the zero arity is part of the requirements for a transducer, but it is never actually used in any transducing context in clojure.core. On the mailing list there's been a post asking the same question as you and proposal of an implementation of transduce
that actually uses the init arity. The jira ticket was declined, however, with the explanation:
Rich asked me to decline the ticket because the init arity of the xform should not be involved in the reducing function accumulation. - Alex Miller
Why, then, is the init arity part of the contract for a transducer if it's not used anywhere? ¯\_(ツ)_/¯
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With