日曜プログラミング

休日趣味でやってるプログラミング関連記事をダラダラと

プログラミング Clojure p150 について

ここで相互再帰の解決手法で trampoline が紹介されてたので試してみる。
Clojure は 1.4 のお話。

(trampoline trampoline-fibo 9)
-> 34

ここまではいいのだが、

(rem (trampoline trampoline-fibo 1000000) 1000)
-> ArithmeticException integer overflow  clojure.lang.Numbers.throwIntOverflow (Numbers.java:1388)

あらま。じゃにわか知識で BigDecimal にしてみる。

 (defn trampoline-fibo [#^BigDecimal n]
   (let [fib (fn fib [f-2 f-1 current]
               (let [f (+ f-2 f-1)]
                 (if (= n current)
                   f
                   #(fib f-1 f (inc current)))))]
     (cond
      (= n 0M) 0M
      (= n 1M) 1M
      :else (fib 0M 1M 2M))))

確認。

(trampoline trampoline-fibo 9M)
-> 34M

(rem (trampoline trampoline-fibo 1000000M) 1000M)
-> 帰って来ない...

まあその後の trampoline 使った my-even? と my-odd? は動いたからいいけどね。
今の所再帰、trampoline、後数値の扱いはちゃんと理解するまでむやみやたらに手を出さない方が良さげ。数値ばかりはその内ちゃんと理解しとかないといけないきがするが。

この辺りも近々出るらしい第2版では修正されそう。