TL;DR
- Clojure の再帰では、関数名の代わりに
recurを使うとメモリ効率が良くなる。recurは関数内で最後に実行する式(末尾再帰)でなければならない。 - Clojure にはデフォルト引数がないので、初期値を渡すラッパー関数を作る。
内容
次のような、カウントダウンする関数を考える。
(defn count-down [number]
(println number)
(if (pos? (dec number))
(count-down (dec number))))
(count-down 5) ; nil
;; 5
;; 4
;; 3
;; 2
;; 1上のように関数名を指定する代わりに、recur を使うこともできる。
(defn count-down [number]
(println number)
(if (pos? (dec number))
(recur (dec number))))recur を使うと、最適化によりメモリ効率が良くなる。また、recur は関数内で最後に実行すべき文(末尾再帰)である必要がある。
次は渡された整数のシーケンスの合計を計算する関数である。
(defn sum [numbers total]
(if (empty? numbers)
total
(recur (rest numbers) (+ total (first numbers)))))
(println (sum [1 2 3 4 5] 0))シーケンスだけを渡して合計を返す関数がほしいときは、次のようなラッパー関数を実装すればよい。Clojure には、デフォルト引数は存在しない。
(defn collection-sum [collection]
(sum collection 0))
(collection-sum [1 2 3 4 5]) ; 15