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.
reduceandapplyare 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 thatapplyis always perfectly idiomatic, whilereduceis 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 ofreducefor 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:reducehas the potential to perform some optimisations to speed things up — perhaps through something likeinternal-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,applywill 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; thenapplywould let you take advantage of those whilereducemight actually slow you down. A good example of the latter scenario occuring in practice is provided bystr: it uses aStringBuilderinternally and will benefit significantly from the use ofapplyrather thanreduce.So, I’d say use
applywhen in doubt; and if you happen to know that it’s not buying you anything overreduce(and that this is unlikely to change very soon), feel free to usereduceto shave off that diminutive unnecessary overhead if you feel like it.