bentaisan
bentaisan

Reputation: 1094

Not understanding reduce with anonymous function

I am reading Living Clojure, and this example of reduce is throwing me off.

(reduce (fn [r x]
          (+ r (* x x)))
        [1 2 3])

[1 2 3] is the input to reduce, along with the anonymous function.

If each member of the vector is passed in, that would only fill in r or x parameters, where does the other parameter come from?

Is there a way to step through to watch the parameters and output change?

Upvotes: 1

Views: 173

Answers (1)

rishat
rishat

Reputation: 8376

There's a description of the first argument on ClojureDocs, but I have to admit it's not really descriptive.

The function you pass as the first argument takes two parameters, the first one is total, the second one is current. If you call reduce with only two arguments, total in first iteration is the first item of the collection, while current in first iteration is the second item of the collection. If you pass three parameters, the second one is initial value that is passed as total in the first iteration, while the first item of the collection is passed as current in first iteration:

(reduce (fn [r x] (+ r x)) 0 [1 2 3])

would iterate like this:

(+ 0 1) ;; initial value and first item of the collection
(+ (+ 0 1) 2) ;; result and second item of the collection
(+ (+ (+ 0 1) 2) 3) ;; result and third item of the collection

while without initial value

(reduce (fn [r x] (+ r x)) [1 2 3])

would iterate like this:

(+ 1 2) ;; no initial value -> first and second item of the collection
(+ (+ 1 2) 3) ;; result and third item of the collection

You could as well just add a println to see each iteration's inputs:

(reduce
  (fn [r x]
      (do
        (println (str "r = " r ", x = " x ", (* x x) = " (* x x) ", (+ r (* x x)) = " (+ r (* x x))))
        (+ r (* x x))))
  [1 2 3])

the result of running it in REPL is

r = 1, x = 2, (* x x) = 4, (+ r (* x x)) = 5
r = 5, x = 3, (* x x) = 9, (+ r (* x x)) = 14
14

Upvotes: 3

Related Questions