Lispの中核をなすのがリストであるため、多くの関数がリストを構築します。consは基本的なリスト構築関数ですが、興味深いことに、Emacsのソースコードではconsよりもlistの方が多く使われています。
この関数は、新しいリスト構造を構築するための最も基本的な関数です。新しいコンスセルを作成し、object1をCARに、object2をCDRに設定します。その後、この新しいコンスセルを返します。引数object1とobject2には任意のLispオブジェクトを指定できますが、多くの場合object2はリストとなります。
(cons 1 '(2))
⇒ (1 2)
(cons 1 '())
⇒ (1)
(cons 1 2)
⇒ (1 . 2)
cons は、リストの先頭に単一の要素を追加する際によく使われます。これを 要素をリストに連結する と呼びます。 6 例えば:
(setq list (cons newelt list))
なお、この例で用いている list という名前の変数と、後述する list という名前の関数との間に矛盾はなく、どのような記号でも両方の目的に使用できます。
この関数は、objectsを要素とするリストを作成します。生成されるリストは常にnilで終端されます。objectsが指定されない場合は、空のリストが返されます。
(list 1 2 3 4 5)
⇒ (1 2 3 4 5)
(list 1 2 '(3 4 5) 'foo)
⇒ (1 2 (3 4 5) foo)
(list)
⇒ nil
この関数は、各要素が object である length
要素のリストを作成します。make-list と make-string を比較してください(文字列の作成 を参照)。
(make-list 3 'pigs)
⇒ (pigs pigs pigs)
(make-list 0 'pigs)
⇒ nil
(setq l (make-list 3 '(a b)))
⇒ ((a b) (a b) (a b))
(eq (car l) (cadr l))
⇒ t
この関数は、sequences のすべての要素を含むリストを返します。sequences
にはリスト、ベクトル、bool-vector、または文字列を指定できますが、通常は最後の要素をリストにする必要があります。最後の引数を除くすべての引数はコピーされるため、どの引数も変更されません。(コピーせずにリストを結合する方法については、リストを再配置する関数 の nconc を参照してください。)
より一般的に、append の最後の引数は任意の Lisp
オブジェクトであり得ます。この最後の引数はコピーも変換もされず、新しいリストの最後のコンスセルの CDR
となります。最後の引数自体がリストである場合、その要素は実質的に結果リストの要素となります。最後の要素がリストでない場合、その結果はドット付きリストとなります。これは、その最後の
CDR が、適切なリストで要求される nil
ではないためです(リストとコンスセル を参照)。
append の使用例を以下に示します。
(setq trees '(pine oak))
⇒ (pine oak)
(setq more-trees (append '(maple birch) trees))
⇒ (maple birch pine oak)
trees
⇒ (pine oak)
more-trees
⇒ (maple birch pine oak)
(eq trees (cdr (cdr more-trees)))
⇒ t
ボックス図を見ると、appendがどのように動作するかが分かります。変数treesにはリスト(pine
oak)が代入され、次に変数more-treesにはリスト(maple birch pine oak)が代入されます。しかし、変数treesは引き続き元のリストを参照しています:
more-trees trees
| |
| --- --- --- --- -> --- --- --- ---
--> | | |--> | | |--> | | |--> | | |--> nil
--- --- --- --- --- --- --- ---
| | | |
| | | |
--> maple -->birch --> pine --> oak
空のシーケンスは、append が返す値に一切寄与しません。その結果、最後の nil 引数によって、直前の引数のコピーが強制的に作成されます:
trees
⇒ (pine oak)
(setq wood (append trees nil))
⇒ (pine oak)
wood
⇒ (pine oak)
(eq wood trees)
⇒ nil
これは、関数 copy-sequence
が考案される前は、リストをコピーする際の一般的な方法でした。シーケンス、配列、ベクトルを参照してください。
ここでは、append の引数としてベクトルや文字列を使用する例を示します:
(append [a b] "cd" nil)
⇒ (a b 99 100)
文字列を文字のリストに変換する方法は以下の通りです。
(append "abcd" nil)
⇒ (97 98 99 100)
関数 string-to-list は、上記の便利なショートカットです。
apply(関数の呼び出しを参照)を使えば、すべてのリストをリストのリストに連結できます:
(apply 'append '((a b c) nil (x y z) nil))
⇒ (a b c x y z)
sequences が指定されていない場合は、nil
が返されます:
(append)
⇒ nil
最後の引数がリストではない例をいくつか挙げます。
(append '(x y) 'z)
⇒ (x y . z)
(append '(x y) [z])
⇒ (x y . [z])
2つ目の例は、最後の引数がシーケンスでありながらリストではない場合、そのシーケンスの要素が結果のリストの要素にはならないことを示しています。代わりに、そのシーケンスは、他のリスト以外の最後の引数と同様に、最終的なCDRとなります。
例外として、最後の引数以外のすべての引数が nil
であり、かつ最後の引数がリストでない場合、戻り値はその最後の引数をそのまま返します(すなわち、この場合の戻り値はリストではありません):
(append nil nil "abcd")
⇒ "abcd"
この関数は、木 tree のコピーを返します。tree がコンスセルである場合、同じ CAR と CDR を持つ新しいコンスセルを作成し、同様に CAR と CDR を再帰的にコピーします。
通常、tree がコンスセル以外の場合、copy-tree は単に tree を返します。ただし、vectors-and-records が nil
以外の場合は、ベクトルやレコードもコピーします(そして、その要素に対して再帰的に処理を行います)。tree
引数にサイクルがあってはなりません。
この関数は、treeの「平坦化」されたコピー、すなわちtreeを根とするコンスセルの木における、nil以外のすべての終端ノード(葉)を含むリストを返します。返されるリスト内の葉の順序は、treeにおける順序と同じです。
(flatten-tree '(1 (2 . 3) nil (4 5 (6)) 7))
⇒(1 2 3 4 5 6 7)
この関数は object をリストとして返します。object が既にリストである場合はそのリストを返し、そうでない場合は object を含む1要素のリストを返します。
これは、リストである場合とそうでない場合がある変数がある場合に通常便利で、例えば次のように記述できます。
(dolist (elem (ensure-list foo)) (princ elem))
この関数は、object を適切なリストとして返します((elisp)Cons Cells を参照)。object が既に適切なリストである場合はこのリストを返し、そうでない場合は object を含む1要素のリストを返します。
object が長いリストになる可能性がある場合は、ensure-list を優先してください。後者の関数は定数時間で動作するのに対し、ensure-proper-list は線形時間で動作するためです。短いリストの場合、この関数は
cons-cell を非リストとして扱うための便利な手段となります:
(ensure-list '(1 . 2))
⇒(1 . 2)
(ensure-proper-list '(1 . 2))
⇒((1 . 2))
この関数は、from から始まり、separation
ずつ増加し、to またはそれ直前で終わる数値のリストを返します。separation は正または負の値を指定でき、デフォルトは 1 です。to が nil であるか、または数値的に from と等しい場合、値は要素数 1 のリスト (from) となります。to が、正の separation を伴う from より小さいか、あるいは負の
separation を伴う from
より大きい場合、それらの引数は空のシーケンスを指定することになるため、値は nil となります。
separation が 0 であり、かつ to が
nil でもなければ from
と数値的に等しくもない場合、それらの引数は無限数列を指定することになるため、number-sequence はエラーを示します。
すべての引数は数値です。浮動小数点引数は、浮動小数点演算が厳密ではないため、扱いが難しい場合があります。例えば、マシンによっては、(number-sequence 0.4 0.6 0.2) が要素1つのリスト (0.4) を返す一方で、(number-sequence 0.4 0.8
0.2) が要素3つのリストを返すということが十分にあり得ます。リストの n
番目の要素は、厳密な数式 (+ from (* n separation))
によって計算されます。したがって、to がリストに含まれることを確実にしたい場合は、to にこの厳密な型の式を渡すことができます。あるいは、to
をわずかに大きな値(separation が負の場合はわずかに負の値)に置き換えることも可能です。
いくつかの例:
(number-sequence 4 9)
⇒ (4 5 6 7 8 9)
(number-sequence 9 4 -1)
⇒ (9 8 7 6 5 4)
(number-sequence 9 4 -2)
⇒ (9 7 5)
(number-sequence 8)
⇒ (8)
(number-sequence 8 5)
⇒ nil
(number-sequence 5 8 -1)
⇒ nil
(number-sequence 1.5 6 2)
⇒ (1.5 3.5 5.5)
There is no strictly equivalent way to add an element to the end of a list.
You can use (append listname (list
newelt)), which creates a whole new list by
copying listname and adding newelt to its end. Or you can use (nconc listname (list newelt)), which modifies listname by following all the CDRs and then replacing the terminating nil. Compare this to adding an element to the beginning
of a list with cons, which neither copies nor
modifies the list.