Arantium Maestum

プログラミング、囲碁、読書の話題

SICPの勉強 問題1.30

SICP1.3.1の問題1.30を解いてみる。

末尾再帰にするのがポイント。問いの中のコードをできるだけ利用するなら:

(defn sum [f a next b]
  (letfn [(iter [a result]
            (if (> a b)
              result
              (recur (next a) (+ (f a) result))))]
    (iter a 0)))

これで先ほどの(integral cube 0 1 0.0001)を試すとStackOverflowを起こさずに正常に計算する。

ただ、clojureなら関数内関数を定義するよりloop/recurのほうが自然:

(defn sum [f a next b]
  (loop [a a result 0]
    (if (> a b)
      result
      (recur (next a) (+ (f a) result)))))

さらにClojure的に書くなら:

(defn sum [f a next b]
  (->> (iterate next a)
       (take-while #(<= % b))
       (map f)
       (apply +)))