@kyanny's blog

My thoughts, my life. Views/opinions are my own.

再帰について

Erlang の勉強をしていて再帰のコードが見やすいしわかりやすいなーと何故か感じるのでなんでかなと考えて、終了条件が成り立つ場合をあたかも別関数であるように独立して書くスタイルが「別ものなんだ」と認識しやすくて理解を助けるのかな、と思った。例えば以下の例だと再帰が終わるとき引数の配列は空っぽですよ、というのが見てすぐにわかる。

-module(my_map).
-export([test/0]).
map(_, []) -> [];
map(F, [H|T]) ->
  [F(H)|map(F,T)].
test() ->
  L = [3,1,4,1,5,9],
  F = fun(I) -> I*2 end,
  map(F,L).

これを例えば Emacs Lisp で書くとこうなるが、ぱっと見たとき再帰の終わりで l が空リストであることを、視覚的にはあんまり把握しやすくない気がする、というか。 '() と書けばいいかというとそういうもんでもなくて。

(defun my-map (f l)
  (cond
   ((null l) nil)
   (t
    (cons (funcall f (car l)) (my-map f (cdr l))))))
(my-map (lambda (x) (* 2 x)) '(3 1 4 1 5 9))

単にいろいろやって自分が以前に比べて再帰というのもをうまくイメージできるようになっただけ、なのかもしれないが、慣れ以上の何かがある気もする。実際何年か前にも Erlang のサンプルコードで fib とか読んでたはずだけどそんなに簡単そうには感じなかったような。