Lisp/基本/List
- この項目は 未完成 です。加筆、改善を歓迎します。
Common Lisp の list は cons セル と呼ばれるもののペアから成り立っています。それぞれのセルは二つの部品を持っていて、それぞれの名前は歴史的経緯で car(セルの最初の部分)とcdr(セルの残りの部分)と言います。
(car . cdr)
List は最初のセルの cdr が、別の consセル へのポインタを保持した cons セル によって実装されています。
空の list は nil としても理解され、そのまま nil という表現で表記されるか、空の list () という表現で表記されます。
cons 関数を使用すれば右部分と左部分がある新しい consセル から成る list を作ることが出来ます。
(cons 'a '()) ⇒ (A)
(cons 'a '(b)) ⇒ (A B)
(cons 'a (cons 'b (cons 'c nil))) ⇒ (A B C)
list ではない consセル を作成することも可能だと憶えておいてください。
(cons 'a 'b) ⇒ (A . B)
これはドットリストと呼ばれます。適正な list にするには連なった consセル の最後の cdr が空の list(nil) にポインタを保持していなければなりません。 list 関数を使用して list を作ることも出来ます。
(list 'a 'b 'c) ⇒ (A B C)
上の式は下の表現と同様です。
(cons 'a (cons 'b (cons 'c '()))) ⇒ (A B C)
(cons 'a (cons 'b (cons 'c nil))) ⇒ (A B C)
(cons 'a '(b c)) ⇒ (A B C)
'(a b c) ⇒ (A B C)
List のそれぞれの要素を取得するには car 関数(あるいは first 関数)、 cdr 関数(あるいは rest 関数)を使用します。
(setf list '(a b c))
(car list) ⇒ a
(first list) ⇒ a
(cdr list) ⇒ (b c)
(rest list) ⇒ (b c)
Common Lisp においては second 関数、 third 関数、 forth 関数(以上 tenth まで続く)が定義されています。 second 関数は cdr や rest とは違うということに注意してください。 cdr と rest は list の最初の要素の後の残りの list を返します。一方で second は list の2番目の要素を返します。
(rest list) ⇒ (b c)
(second list) ⇒ b
(third list) ⇒ c
(fourth list) ⇒ nil
List は連なった順序になっているので、順序を操作する関数は list も操作します。
(subseq list 0 1) ⇒ (a)
(subseq list 0 2) ⇒ (a b)
nth 関数は list から選択した項目を抜き出します。
(nth 0 list) ⇒ a
最初の項目は 0th だということに注意してください。 Common Lisp はいくつもの list を操作するフォーム(関数やマクロのことです)を持っています。 mapcar は list のそれぞれの要素を、一度に一つずつ新しい list を作り出す処理に使うことができます。
(defun add2 (n)
(+ 2 n))
(mapcar #'add2 '(1 2 3)) ⇒ (3 4 5)
上の例では、一つの list に対して mapping しています。そのため単項関数(引数を一つとる関数)を使いました。 #' は引数として関数を渡すための特殊な方法です。このことに関しては次の章で詳しく紹介します。一つ以上の list を map することも可能です。関数は list にある同じ数の引数をとらなくてはなりません。
(mapcar #'+ '(1 2 3) '(4 5 6)) ⇒ (5 7 9)