Apply vs. Reduce

When they are the same, and when they are different.

October 11, 2021

A quick REPL session will demonstrate that there are multiple ways to calculate a 'sum':

$ clj
Clojure 1.10.3
user=> (reduce + [1 2 3 4 5])
15
user=> (apply + [1 2 3 4 5])
15
user=> (reduce str ["a" "b" "c"])
"abc"
user=> (apply str ["a" "b" "c"])
"abc"

So, what's the difference between apply and reduce? Is one better than the other? As usual, StackOverflow beat me to the punch. Here's a snippet from the answer by Michał Marczyk:

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.

user=> (reduce + [1 2 3 4 5])
; translates to: (+ (+ (+ (+ 1 2) 3) 4) 5)

user=> (apply + [1 2 3 4 5])
; translates to: (+ 1 2 3 4 5)

From the answer by David Rz Ayala:

be careful, they are not the same:

user=> (apply hash-map [:a 5 :b 6])
;= {:a 5, :b 6}
user=> (reduce hash-map [:a 5 :b 6])
;= {{{:a 5} :b} 6}

Michał Marczyk also points out that the str function (source) makes use of the Java StringBuilder to optimize its work. In this case, which would be the best (most efficient) choice?

The correct answer is... (click me)

(apply str ["a" "b" "c"])