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.

Reply via email to