DEV Community

Nick Bauman
Nick Bauman

Posted on

From loop recur to reduce

In Clojure, do you find yourself reaching for a loop recur but you know you should be using reduce? Here's a really simple way to break out of that habit.

Let's start with and example. Starting with a2d which is the result of invoking (to-array-2d [[11 2 4] [4 5 6] [10 8 -12]]) and len is the size of the matrix. Which is 3.

This function, written with a loop/recur, calculates the "diagonal sum" of the values of a square matrix of some size.

(defn accu [a2d len]
 (reduce +
  (loop [vals []
         i    (- len 1)]
   (if (> len (count vals))
    (recur (conj vals (aget a2d i i)) (dec i))
    vals))))
Enter fullscreen mode Exit fullscreen mode

So invoking this function:

(accu (to-array-2d [[11 2 4] [4 5 6] [10 8 -12]]) 3)
=> 4
Enter fullscreen mode Exit fullscreen mode

Returns 4 because 11 + 5 + -12 = 4

So what does the reduce version look like?

(defn accu [a2d len]
 (reduce +
  (reduce #(conj %1 (aget a2d %2 %2)) [] (reverse (range len)))))
Enter fullscreen mode Exit fullscreen mode

Notice how the relevant code is almost exactly the same. Both use (conj vals (aget a2d i i)) (dec i) to solve the problem. The loop/recur version has much more housekeeping and is not as fast as the reduce version.

Top comments (0)