末尾再帰をやってみる。
(defun my-fact (n) ; 普通の再帰
(if (= n 0) 1
(* n (my-fact (1- n)))))
↓
(defun my-fact (n) ; 末尾再帰
(my-fact-loop n 1 1))
(defun my-fact-loop (n i p)
(if (> i n) p
(my-fact-loop n (1+ i) (* i p))))
;; test
(trace my-fact)
(trace my-fact-loop)
(my-fact 3)
Calling (my-fact-loop 3 1 1)
Calling (my-fact-loop 3 2 1)
Calling (my-fact-loop 3 3 2)
Calling (my-fact-loop 3 4 6)
my-fact-loop returned 6 ; 一番奥で求めた値を持って帰るだけなので、
my-fact-loop returned 6 ; ちゃんと末尾再帰になってる
my-fact-loop returned 6
my-fact-loop returned 6
6
うまくいっているようだが、やってることがさっぱりわからん。
末尾再帰になるように、補助関数を用意するのは分かる。
でもその引数をどうやって決めるのかとか、終了条件とかそのとき返す値の決め方がさっぱりだ。意味わからん。
なるべく再帰にしたいということは、なんとなく分かる。
再帰で書くと、ループで書いたものより、なにをやってるかがわかりやすいぞ
↓
じゃあ、再帰で書いてみよう
↓
とくに末尾再帰にすると、ループ処理に展開されるから早くなるし、スタック使わないからエレガントだ
↓
じゃあ、末尾再帰にしてみよう
という流れは分かるんだが・・・。
まあ、どうせ xyzzy には末尾再帰の最適化がないらしいので書けなくてもいいか。
と今は逃げておく。
0 コメント :
コメントを投稿