引き続き、"Common Lisp: A Gentle Introduction to Symbolic Computation"を読みながら基礎固めをしていく。
Lispというのは"LISt Processing"のことらしいのでリストは重要な位置を占めるのだろう。
Contents
リストの内部構造
内部の構造を理解しておくとリストに対する操作を考えやすくなりそうだ。
連結リスト
Common Lispのリストはいわゆる連結リストの構造をしている。例えば下記のようなリストを考える。
(a b c d)
内部的には各要素はそのデータを指すポインタと次の要素を指すポインタの対となっている。また最後の要素における次の要素を指す部分はNIL
となる。
この対となっている箱をコンスセル(cons cell)という。
(a b c d)
の内部構造の図
空リスト
空リスト()
とNIL
は等価。リストではあるがコンスセルは含まれない。
リストに対する操作
FIRST, REST
FIRST
: リストの最初の要素を返す。
REST
: リストの一つ目の要素をのぞいた残りを返す。
上記の内部構造の最初のコンスセルのそれぞれのポインタを返すと考えればよさそうだ。
(a b c d)
にそれぞれFIRST
、REST
を適用した場合は、
a
と(b c d)
が返ってくる。
FIRST
と同様にSECOND
、THIRD
等もある。SECOND
はREST
のFIRST
、THIRD
はREST
のREST
のFIRST
と考えられる。
CAR, CDR
Lispの意味の分からない名前の代表。
"CAR"は"Contents of Addresss portion of Register"の頭文字からきている。
"CDR"は"Contents of Decrement potion of Register"の頭文字からきている。
大昔のLispを動かしていたマシンのregisterの各部のことらしい。
動作としては、CAR
はFIRST
と同じ。CDR
はREST
と同じ。
CAR
とCDR
は合成することができる。
CDR
のCAR
はCADR
。
CDR
のCDR
のCAR
はCADDR
。
4つの合成まで対応しているらしい。パッと見てわかりにくいのだが使っている人はいるのか?
リスト以外をCAR
、CDR
に入力するとエラーになる。
ただし、NIL
のCAR
、CDR
はどちらもNIL
。この関係はプログラミングの利便性のためらしいが、今のところ何が便利なのかはわからない。Schemeではエラーらしい。
CONS
"CONS"は"constructure"の略。CONS
を使用してコンスセルを作ることができる。
a
と(b c d)
に対してCONS
を適用すると(a b c d)
ができる。
リストの最後のコンスセルのCDR
はNIL
なので、a
とNIL
にCONS
を適用すると(a)
となる。
(a b c d)
をCONS
で作るには、
a
とb
とc
とd
とNIL
のCONS
のCONS
のCONS
のCONS
とすればよい。
CONSとCAR,CDRの関係
上記のようにCAR
とCDR
はリストの最初のコンスセルの二つのポインタを返す。その二つのポインタでコンスセルを作ればもとのリストになるはずだ。
- リストの
CAR
とCDR
にCONS
を適用すると元のリストになる。
LIST
CONS
だけでリストは作れるが、LIST
を使えばもっと楽にリストを作ることができる。a
、b
、c
、d
にLIST
を適用すると(a b c d)
が返ってくる。
LISTP, CONSP
リストかどうか、コンスセルかどうかを判定するpredicatesがある。それぞれLISTP
、CONSP
である。先に書いたようにリストはコンスセルなのでこれらはほぼ同じ機能である。
唯一の違いはNIL
に適用した際の挙動。NIL
のLISTP
はT
だが、NIL
のCONSP
はNIL
である。空リスト(=NIL)はリストだがコンスセルはないということか。
まとめ
- リストはコンスセルで構成されている。
- 空リスト
()
とNIL
は等価 CAR
,CDR
,FIRST
,REST
でリストの先頭要素と残りを取り出せる。CONS
でコンスセルを作る。- リストの
CAR
とCDR
にCONS
を適用すると元のリストになる。 LIST
でリストを作る。
コメント