よせばいいのに、Gaucheを用いてLISPの2大方言の1つSchemeの勉強(?)なんてしていて、2つのリストを繋げたリストを返す標準的な関数「append」を自前で作ってみた。ところが、
(define (my-append list1 list2)
(if (null? list1)
list2
(my-append (cdr list1) (cons (car list1) list2))
)
)
としてしまうと、
gosh> (my-append '(0 1 2 3 4) '(5 6 7 8 9))
(4 3 2 1 0 5 6 7 8 9)
と、list1部分の要素の並びが逆転してしまう。
まぁ、しゃあない、LISPってそういうものなのだろうと諦めていたら(考えてみりゃ、んなわきゃない)、これまたよせばいいのに今度はLISPの本を読んでいて、次のように書けばいいことを知った。
(define (my-append2 list1 list2)
(if (null? list1)
list2
(cons (car list1) (my-append2 (cdr list1) list2))
)
)
これだと、
gosh> (my-append2 '(0 1 2 3 4) '(5 6 7 8 9))
(0 1 2 3 4 5 6 7 8 9)
とちゃんとうまくいく。
(my-append (cdr list1) (cons (car list1) list2))
と
(cons (car list1) (my-append2 (cdr list1) list2))
の本質的な違いは、「append」を先にするか「cons」を先にするかだけで、欲しい結果を生み出すだけでなく、より「再帰的処理」らしいのはやはり後者。しかし、この「やりたいことは既に終わっている」(「お前は既に死んでいる」!?)ものとして処理を記述する、という感覚はわかっていてもそうそう簡単には身に付かない。身に付かないから、こういうコードはなかなか思い付かない…。
こんなのはLISPの初歩の初歩なのだが…、再帰は奥が深くて面白い。
※上記のコードには、html上でインデントさせるために全角スペースを入力しています。そのため、このままコピーして実行してもエラーが出ると思います。
※上記のコードの「my-append」「my-append2」の部分を単に「append」と書くと、Gaucheで既に定義されている(?)「append」関数が用いられてしまうようです。

0