loop recur から reduce へ


Clojure では、recur を使用する必要があることを知っているのに、ループの再帰を求めていますか?その習慣を断ち切るとても簡単な方法があります.

例から始めましょう. a2d を呼び出した結果である (to-array-2d [[11 2 4] [4 5 6] [10 8 -12]]) から始まり、len が行列のサイズです.これは 3 です.

loop/recur で記述されたこの関数は、あるサイズの正方行列の値の「対角和」を計算します.

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


したがって、この関数を呼び出す:

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


11 + 5 + -12 = 4 であるため、4 を返します.

では、reduce バージョンはどのように見えるでしょうか?

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


関連するコードがほぼ同じであることに注意してください.どちらも (conj vals (aget a2d i i)) (dec i) を使用して問題を解決します. loop/recur バージョンはハウスキーピングがはるかに多く、reduce バージョンほど高速ではありません.