consってなんだろね。Lispに初めて触れる人にとってこれが一番変態に映るんじゃ ないかな。「なんで一個しか足せんのじゃ、appendの方が便利やん」とか、「な んで頭に足すねん、けつの方が便利やん」とか、「要素一個足すなら分かりやす いが、リストとリストをくっつけたらどうなるかよく分からん」とか、「よく括 弧の中に書くピリオド(.)はなんじゃらほい」とか。
確かにわけ分からん。
原理を知るまでは。
consってナニモノかっていうと、答は単純。
consセルを一個作る
こんだけ。これ以上でも以下でもない。consセルって知ってる人は知ってると思 うが、要するにデータを二個入れられる箱だ。二人乗りのトロッコを思い浮かべ るといい。前の席と後の席がある。ただし、後ろにさらに一個トロッコを繋げる 場合は後ろの座席を潰して連結器を置いて次のトロッコまで伸ばす必要がある、 そんな風に考えるとconsセルに近い。
トロッコに二人乗る様子を描くとこんな感じか。進行方向は左。
[ 太郎 | 花子 ]
まんなかの縦棒(|)は仕切りの板だ。仲良く二人乗っている。これをS 式で表現するとこう。
(太郎 . 花子)
ほれ、まったくおんなじじゃろ。じゃあ今度は3人とか4人とか、たくさん乗せよ う。こうなると、トロッコ一台じゃ足りん。それにあとで定員殖やすこと考える と最初からトロッコを繋げることを想定して後部座席は連結器を置くんだと決め 打ちしちゃった方がええ。とりあえず二人。
[ 太郎 | 連結器-]--[ 花子 | 空席 ]
さてS式ではどう書こう。ここで一つお約束。連結している様子を "--" でたく さん書くとスペースがもったいないので、「連結器」の部分にはその先につながっ てるトロッコを書いちゃっていいことにする。つまり、
[ 太郎 | [ 花子 | 空席 ] ]
こゆこと。実際に後部座席にトロッコがまるごと乗ってるわけじゃないが、イメー ジとしてはそんな感じ。これならすぐにS式にできる。
(太郎 . (花子 . 空席))
お、Lispっぽいぞ。じゃあ二郎君も乗せてみよう。
[ 太郎 | 連結器-]--[ 花子 | 連結器-]--[ 二郎 | 空席 ]
これを簡略表記にすると、
[ 太郎 | [ 花子 | [ 二郎 | 空席 ] ] ]
でけた。S式は、
(太郎 . (花子 . (二郎 . 空席)))
もう分かった。何個でも書けるぞ。ていうか、難しいというより、書くのがめん どいだけやん。
さて、三郎君がやってきた。
「ねーねー、僕も乗せて」
最初は手ぶらでやってきた。ドアホウ、乗りたいんだったらトロッコ1ユニット 持っといで。そしたらくっつけたるがな。「はーい」
今度はトロッコ持ってやってきた。
「ねーねー、僕のこれもくっつけてー」
ほいきた。じゃあ適当にくっつけな。「どこにつけたらいいの?」
太郎君は「あー、後ろの方に空いてるとこがあるからさー、そこに繋いで」
とはいったものの、三郎君がさらに花子ちゃんに同じ質問をしていたのでイライ
ラしてきた。「はよせーな。あー、もうええわい、わしがちみの後ろについたる
わ、ガチャんこ」
最初からそうした方が早かった。
3人ならまだいいが、10人いたら時間がかかってしょうがない。どうせ「どこに つけたらいいの?」を10回繰り返すに決まってる。てことで、
これがcons関数。
(cons 参加希望者 トロッコ列)
こうすると、希望者君にトロッコを一基割り当てて、トロッコ列先頭に足してく れる。そしてめでたく三郎君は先頭に参加した。
(三郎 . (太郎 . (花子 . (二郎 . 空席))))
書くのが面倒になって来た。じゃあ、こういう風にトロッコを繋げる場合、仕切 りと括弧を書くのはよそうや。という約束を決めて表現したのが、
(三郎 太郎 花子 二郎)
ということである。括弧の中に並べて書く裏には、内側で省略されている括弧が あるのだと気づくと、Lispプログラムの中にピリオドなんぞが入っていても恐く ない。
でも、後から来たやつが先頭に来ちゃうのはむかつかん? ひそかにLispではデー タの順番なんてのはどうでもよかったりする場合が多い。それはまたいずれ。