tags:

views:

191

answers:

4

I understand the conceptual difference between reduce and apply:

(reduce + (list 1 2 3 4 5))
; translates to: (+ (+ (+ (+ 1 2) 3) 4) 5)

(apply + (list 1 2 3 4 5))
; translates to: (+ 1 2 3 4 5)

However, which one is more idiomatic clojure? Does it make much difference one way or the other? From my (limited) performance testing, it seems reduce is a bit faster.

+5  A: 

It doesn't make a difference in this case, because + is a special case that can apply to any number of arguments. Reduce is a way to apply a function that expects a fixed number of arguments (2) to an arbitrarily long list of arguments.

Greg Harman
+1  A: 

I normally find myself preferring reduce when acting on any kind of collection - it performs well, and is a pretty useful function in general.

The main reason I would use apply is if the parameters mean different things in different positions. In this case they don't, so either works.

mikera
+13  A: 

reduce and apply are of course only equivalent (in terms of the ultimate result returned) for associative functions which need to see all their arguments in the variable-arity case. When they are result-wise equivalent, I'd say that apply is always perfectly idiomatic, while reduce is equivalent -- and might shave off a fraction of a blink of an eye -- in a lot of the common cases. What follows is my rationale for believing this.

+ is itself implemented in terms of reduce for the variable-arity case (more than 2 arguments). Indeed, this seems like an immensely sensible "default" way to go for any variable-arity, associative function: reduce has the potential to perform some optimisations to speed things up -- perhaps through something like internal-reduce, a 1.2 novelty recently disabled in master, but hopefully to be reintroduced in the future -- which it would be silly to replicate in every function which might benefit from them in the vararg case. In such common cases, apply will just add a little overhead. (Note it's nothing to be really worried about.)

On the other hand, a complex function might take advantage of some optimisation opportunities which aren't general enough to be built into reduce; then apply would let you take advantage of those while reduce might actually slow you down. A good example of the latter scenario occuring in practice is provided by str: it uses a StringBuilder internally and will benefit significantly from the use of apply rather than reduce.

So, I'd say use apply when in doubt; and if you happen to know that it's not buying you anything over reduce (and that this is unlikely to change very soon), feel free to use reduce to shave off that diminutive unnecessary overhead if you feel like it.

Michał Marczyk
Great answer. On a side note, why not include a built-in `sum` function like in haskell? Seems like a pretty common operation.
dbyrne
Thanks, happy to hear that! Re: `sum`, I'd say that Clojure has this function, it's called `+` and you can use it with `apply`. :-) Seriously speaking, I think in Lisp, in general, if a variadic function is provided, it's not usually accompanied by a wrapper operating on collections -- that's what you use `apply` for (or `reduce`, if you know that makes more sense).
Michał Marczyk
+3  A: 

Opinions vary- In the greater Lisp world, "reduce" is definitely considered more idiomatic. First, there is the variadic issues already discussed. Also, some Common Lisp compilers will actually fail when "apply" is applied against very long lists because of how they handle argument lists.

Amongst Clojurists in my circle, though, using "apply" in this case seems more common. I find it easier to grok and prefer it also.