Reducing functions have three arities: 0-arity: returns the initial state 1-arity: handles completion 2-arity: reduce step function
Using arities to denote different functionality is a little odd, but it does make sense for functions like addition and conjoin: (+) => 0 (+ 1) => 1 (+ 1 2) => 3 (conj) => [] (conj [1]) => [1] (conj [1] 2) => [1 2] The 1-arity state is often just the identity function, but for channels and I/O processes it's useful for closing resources, flushing buffers and generally cleaning up after itself. You're getting strange results because your reducing function is strange. You're not thinking about how the different arities are used. Look at it another way: (defn +ten ([] 10) ;; initial state is 10 ([x] (+ 10 x)) ;; on completion, add 10 ([x y] (+ 10 x y)) ;; step function adds x and y and 10 So let's take a look at your initial transduce again: (transduce (map (partial * 2)) +ten [0 1 2]) You're essentially saying: "Set the initial value to 10. Double the values in the array and add then together in pairs. Every time you add a pair of numbers, add 10 to the result. On completion, add 10 again." - James On 5 December 2014 at 09:51, Ivan Mikushin <i.mikus...@gmail.com> 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. > -- 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.