I find these examples very memorable. Despite the doc strings clearly stating the differences between transduce and reduce, one can still hastily assume that transducing [0 1 2] will have 0 as the init argument.
I will add that the culprit is in defining the +ten's arguments with [& args] form, which allows the function to be called without args (or with any number of args). (apply + 10 []) => 10 (+ten) => 10 Which means these are equivalent: (transduce (map (partial * 2)) +ten [0 1 2]) (transduce (map (partial * 2)) +ten 10 [0 1 2]) Reducing [0 2 4] yields 26. With 10 as init value it yields 46. After consuming all elements of coll, the 1-arity fn is run to provide the return value. Due to the [& args] form the completion stage evaluates (+ten 46) and returns 56. On Friday, December 5, 2014 10:51:49 AM UTC+1, Ivan Mikushin wrote: > First: transducers are a very cool idea, and I'm really looking forward to > clojure 1.7 release when we'll be able to use them in production code. > > Now, clojure 1.7 is still alpha, so here's my feedback while it's not > (too) late. > > transduce has a pretty unintuitive behaviour. Suppose, you've got some > transformation, which you are going to apply to your reducing function and > finally use it to reduce a collection. Currently, you have to know the > implementation detail of transduce to approach this task. > > Just a couple examples. > > Example 1: > (defn +ten [& args] > (println (str "+ten " args)) > (apply + 10 args)) > > (transduce (map (partial * 2)) +ten [0 1 2]) ;; Should equal *26*, right? > +ten > +ten (10 0) > +ten (20 2) > +ten (32 4) > +ten (46) > => *56* > > (transduce (map (partial * 2)) +ten 0 [1 2]) ;; OK, now this SHOULD equal > *26*... > +ten (0 2) > +ten (12 4) > +ten (26) > => *36* > > (transduce (map (partial * 2)) +ten []) ;; Let's see: just no-args (+ten) > *once* here... > +ten > +ten (10) > => *20* > WAT? > > Example 2: > (transduce (map (partial * 2)) max 0 [1 2]) > => *4* > (transduce (map (partial * 2)) max [0 1 2]) ;; Should give *4*... > *ArityException Wrong number of args (0) passed to: core/max > clojure.lang.AFn.throwArity (AFn.java:429)* > WAT? > > I know transduce requires f to accept arity 1 (as well as 0 and 2). > Looking at the current implementation ( > https://github.com/clojure/clojure/blob/clojure-1.7.0-alpha4/src/clj/clojure/core.clj#L6518), > > we can see this arity is applied just before returning result. Why? > > Why not use it (okay, (xform f)) when there's no init AND coll has just > one element. > > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.