例えば, even/oddならこんな感じ.
(defn even-odd? [even-or-odd n]
(loop [status even-or-odd n n]
(cond
(= status :even)
(if (= n 0)
true
(recur :odd (dec n)))
(= status :odd)
(if (= n 0)
false
(recur :even (dec n))))))
こう書いておいて,
user> (even-odd? :odd 9)と呼び出すとか. cond節が冗長になりますが, declare, defnと書いて, 無名関数で囲って, trampolineで待ち受けさせるのと大差ないかなと....思ったのですが, 比べてみると, やっぱり読みにくい. trampoline版のほうがシンプルですね.
(declare my-odd?)
(defn my-even? [n]
(if (= n 0)
true
#(my-odd? (dec n))))
(defn my-odd? [n]
(if (= n 0)
false
#(my-even? (dec n))))
適当に測ってみると少し早くなった程度.
user> (time (trampoline my-even? 10000000)) "Elapsed time: 2127.23756 msecs" true user> (time (even-odd? :even 10000000)) "Elapsed time: 1781.678006 msecs" trueしかし, 相互再帰を書く時の選択肢としてはありかなと思ったりしてます.
0 件のコメント :
コメントを投稿