検索エンジンから来た人に注意

このマニュアルは、Emacs ver. 19.x 向けのマニュアルを Mule 2.x の開発にあたり邦訳したものを、 電脳外道学会がミラーリングしているものであり、旧版製品パラノイアであるところの椅子人の趣味によるものです。

しかしながら、現在の Emacs の主流は ver. 20 以降であり、ver 19.x と ver 20.x とでは、仕様の違いが少なからずあります。

したがって、一般的な Emacs ユーザーにとっては、 このマニュアルと実機の動作とが符合しない場合があります。
特に、公開用の Emacs Lisp コードを書こうとする人は、 新バージョンのマニュアル(英語)を参照することを強くおすすめします。


トップページ&リンク | マニュアルの目次 | 検索
Go to the first, previous, next, last section, table of contents.


リスト

リスト(list)は、零個もしくは数個の要素(どんなLispオブジェク トでも構いません)の並び(sequence)です。リストとベクタとの重要な違 いは、複数のリストの間でその一部を共有することが可能なことです。さら にリスト全体をコピーすることなしに要素を加えたり、削除したりすることも 可能です。

リストとコンス・セル

Lispでは、リストはプリミティブなデータ型ではありません。リストは コンス・セル(cons cell)から構成されます。個々のコンス・セルは順 序づけられた対のデータ・オブジェクトです。コンス・セルは、二つのLispオ ブジェクトを指します。一つはCARと呼ばれ、もう一つはCDRと 呼ばれます。これらの名前は伝統的なものです(section コンス・セル型とリスト型参照)。 CDRは "could-er" と発音します。

リストは、その各要素が一つのコンス・セルである、一継りのコンス・セル の集まりです。慣習により、そのそれぞれのコンス・セルのCARはリス トの要素を持ち、CDRはコンス・セルをつなぐために用いられます。つ まり、それぞれのコンス・セルのCDRは、次のコンス・セルを指します。最 後のコンス・セルのCDRはnilです。このCARと CDRとの非対称性はただ単に慣習によるものです。コンス・セル自体は、 CARもCDRも同じ性質を持っています。

ほとんどのコンス・セルがリストの一部分として用いられることから、 リスト構造(list structure)という言葉は、コンス・セルから構成される 全ての構造を意味します。

シンボルnilは、シンボルとしてだけではなく、要素を持たないリス トとしても扱われます。便宜上シンボルnilは、そのCDRに(また そのCARにも) nilをもつものとして扱われます。

空ではないリストlのCDRは、lの最初の要素以外の全て の要素を含むリストです。

箱を用いたリストの表現

コンス・セルは、一組の箱として表現することができます。最初の箱が CARを表わし、二つめの箱がCDRを表わします。二つのコンス・セ ルからなる、(tulip lily)という二つの要素からなるリストは、次のよう に表されます。

それぞれの箱の組は、コンス・セルを表わします。それぞれの箱がリスト・オブ ジェクトを "参照する(refer to)" とか、"指し示す(point to)" とか、 あるいは、"含む(contain)" などと表現します(これらの言葉は同義です)。 先頭のコンス・セルのCARである最初の箱には、tulipというシ ンボルが入っています。そのCDRから2番目のセルへの矢印は、最初の コンス・セルのCDRが2番目のコンス・セルを指し示していることを表 します。

このリストは、次のような別の箱表記で表わすこともできます。

次はより複雑な例です。((pine needles) oak maple)という三つの 要素からなるリストを表わし、その最初の要素は、二つの要素からなるリストです。

このリストを最初の箱表記で表すと、次のようになります。

コンス・セルやリストに対する、読込みと印字の構文、および、リストの "箱と矢印"を用いた表記に関するより詳しい解説は、See section コンス・セル型とリスト型

リストに関する述語

以下の述語(predicate)は、リスト・オブジェクトがアトムであるか、コン ス・セルであるか、リストであるか、もしくはnilであるかを調べる ために用いられます(これらの述語の多くは、他のものを用いて定義できますが、 非常によく使われるので、全部を用意しておくことに意味があるのです)。

Function: consp object
この関数はobjectがコンス・セルであればtを返し、そうでな ければnilを返します。nilはリストですが、コンス・ セルではありません。

Function: atom object
この関数は、objectがアトムであればtを返し、そうでなけれ ばnilを返します。コンス・セル以外の全てのオブジェクトはアトムで す。nilはアトムであり、かつリストでもあります。アトムであり、 かつリストであるのは、唯一nilだけです。
(atom object) == (not (consp object))

Function: listp object
この関数は、objectがコンス・セルもしくはnilであれば tを返し、そうでなければnilを返します。
(listp '(1))
     => t
(listp '())
     => t

Function: nlistp object
この関数は、listpの反対の働きをします。つまりobjectが リストでなければtを返し、そうでなければnilを返します。
(listp object) == (not (nlistp object))

Function: null object
この関数は、objectnilであればtを返し、そうで なければnilを返します。この関数はnotと同じものですが、 わかりやすいように、objectがリストである場合nullを、 真か偽かを表わす場合にはnotを用います(section 条件を結合するための構文要素notを参照)。
(null '(1))
     => nil
(null '())
     => t

リストの要素の参照

Function: car cons-cell
この関数は、コンス・セルcons-cellの最初のポインタによって指し示され る値を返します。これを簡単に、この関数はcons-cellのCAR を返す、とも表現します。

特別な場合として、cons-cellnilの場合、carnilを返すと定義されます。したがって、いかなるリストもcar の有効な引数となります。引数がコンス・セルでもnilでもない場 合、エラーが通知されます。

(car '(a b c))
     => a
(car '())
     => nil

Function: cdr cons-cell
この関数は、コンス・セルcons-cellの二つめの箱のポインタによって指し示さ れる値を返します。この関数はcons-cellのCDRを返す、とも 表現されます。

特別な場合として、cons-cellnilの場合、cdrnilを返すと定義されます。したがって、いかなるリストもcdrの 有効な引数となります。引数がコンス・セルでもnilでもない場合、エラー が通知されます。

(cdr '(a b c))
     => (b c)
(cdr '())
     => nil

Function: car-safe object
この関数は、データ型がコンス・セル以外である場合でもエラーとならず、 CARを得ることができます。objectがコンス・セルの場合は objectのCARを返し、そうでなければnilを返します。 これは、objectがリストでない場合にエラーを通知するcarと 対照的です。
(car-safe object)
==
(let ((x object))
  (if (consp x)
      (car x)
    nil))

Function: cdr-safe object
この関数は、データ型がコンス・セル以外である場合でもエラーとならず、 CDRを得ることができます。objectのコンス・セルの場合は objectのCDRを返し、そうでなければnilを返します。 これは、objectがリストでない場合にエラーを通知するcdrと 対照的です。
(cdr-safe object)
==
(let ((x object))
  (if (consp x)
      (cdr x)
    nil))

Function: nth n list
この関数は、listn番目の要素を返します。最初の要素は0 番目とされます。つまりlistのCARは0番目の要素です。も し、listの長さがn以下の場合はnthnilを 返します。

nが負である場合、nthlistの最初の要素を返 します。

(nth 2 '(1 2 3 4))
     => 3
(nth 10 '(1 2 3 4))
     => nil
(nth -3 '(1 2 3 4))
     => 1

(nth n x) == (car (nthcdr n x))

Function: nthcdr n list
この関数は、listn番目のCDRを返します。別の表現を すると、listの最初のn個のリンクを取り除き、残ったものを 返します。

nが0以下の場合、nthcdrlist全体を返しま す。listの長さがn以下の場合は、nthcdrnilを返します。

(nthcdr 1 '(1 2 3 4))
     => (2 3 4)
(nthcdr 10 '(1 2 3 4))
     => nil
(nthcdr -3 '(1 2 3 4))
     => (1 2 3 4)

コンス・セルとリストの生成

リストはLispの中核となる概念であるため、多くの関数がリストを生成しま す。consが基本的なリストを生成する関数です。しかし、興味深いことに、 Emacsのためのソース・コードではconsよりもlistの方が多 く使われています。

Function: cons object1 object2
この関数は、新しいリスト構造を作るために用いられる基本的な関数です。新し いコンス・セルを作り、object1をCARに、さらに object2をCDRにします。そしてこの新しいコンス・セルを返し ます。引数object1object2はどんなリスト・オブジェクト でも構いません。しかし、ほとんどの場合object2はリストです。
(cons 1 '(2))
     => (1 2)
(cons 1 '())
     => (1)
(cons 1 2)
     => (1 . 2)

consは、しばしばリストの先頭に新しい要素を加えるために用いられます。 これを要素をリストにconsするといいます。たとえば、

(setq list (cons newelt list))

この例で用いられたlistという変数と、次に説明するlist という関数との間で衝突が起きないことに注意してください。いかなるシンボ ルも変数名、関数名、両方の目的に使うことができます。

Function: list &rest objects
この関数は、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

Function: make-list length object
この関数は、長さがlengthで、その全ての要素がobjectと同じ 値をもつリストを生成します。make-listmake-stringを比 較してください(see section 文字列の生成)。
(make-list 3 'pigs)
     => (pigs pigs pigs)
(make-list 0 'pigs)
     => nil

Function: append &rest sequences
この関数は、sequencesの全ての要素を含むリストを返します。 sequencesはリストかベクタ、もしくは文字列のいずれでも構いませ んが、最後の引数はリストであるべきです。最後のものを除く全て の引数は、コピーされるので、いずれも変更されません。

もっと一般化していえば、appendの最後の引数は、どんなLispオブジェクトで も構いません。最後の引数はコピーも変換もされません。新しいリストの最後 のコンス・セルのCDRになります。最後の引数自身がリストである 場合、その要素はすべてそのまま結果のリストの要素になります。最後 の要素がリストではない場合は、最後のCDRがnilではないた め、真のリストにはならず、結果は "ドット・リスト(dotted list)" になります。

コピーをせずにリストを連結する方法は、section リストを再構成する関数nconc を参照してください。

次に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はもとのリストを参照したままです。

sequencesの中に空のsequenceがあっても、appendが返す値には、 何の影響も与えません。その結果、最後の引数をnilにすることで、 そこまでの引数のコピーを生成することができます。

trees
     => (pine oak)
(setq wood (append trees ()))
     => (pine oak)
wood
     => (pine oak)
(eq wood trees)
     => nil

かつて、関数copy-sequenceが考案されるまでは、これがリストを生成する 普通の方法でした。See section シーケンス、配列、ベクタ

applyを用いることで、リストの中のそれぞれのリストに含まれる全ての リストをappendすることができます。

(apply 'append '((a b c) nil (x y z) nil))
     => (a b c x y z)

appendsequencesが与えられなかった場合、nilが返されます。

(append)
     => nil

これらは最後の引数がリストでない場合の例です。

(append '(x y) 'z)
     => (x y . z)
(append '(x y) [z])
     => (x y . [z])

二つめの例は、最後の引数が列ではあるがリストではないとき、その 列の各要素は結果のリストの要素にはならないことを示しています。 その代わりその列は、リストではない最後の引数と同様に、最後の CDRとなります。

append関数は、引数に整数をとることもできます。その整数の10進印字 表現を作って数字の文字列へ変換し、もとの整数のかわりにこの文字列を使用し ます。この機能を使わないでください。我々はこの機能を取り除く予 定です。もしすでにあなたのプログラムでこの機能を使用しているのであれば、 ただちに修正してください !整数を10進数に変換する適切な方法は format (see section 文字列の書式変換)もしくは number-to-string (see section 文字と文字列間の変換)を用いることです。

Function: reverse list
この関数は、listの要素を逆順に並べた新しいリストを生成します。 もとの引数listは変更されません
(setq x '(1 2 3 4))
     => (1 2 3 4)
(reverse x)
     => (4 3 2 1)
x
     => (1 2 3 4)

リスト構造の変更

setcarsetcdrというプリミティブを用いて、コンス・セルの CARとCDRの内容を変更することができます。

Common Lisp注意書き: Common Lispには、リスト構造を変更する関数 rplacarplacdがあります。これらはsetcarsetcdrと同様な処理を行ないますが、setcarsetcdr が新たなCARやCDRの値を返すのに対してCommon Lispの関数は コンス・セルを返します。

setcarによるリスト要素の変更

setcarによって、コンス・セルのCARの変更が行なわれます。リスト に対して用いられた場合、setcarは、リストのある要素を別の要素で置 き換えます。

Function: setcar cons object
この関数はconsのCARをobjectに置き換えます。 objectの値を返します。たとえば、
(setq x '(1 2))
     => (1 2)
(setcar x 4)
     => 4
x
     => (4 2)

あるコンス・セルがいくつかのリストで共有される構造の一部分であるときは、 そのコンス・セルに新しいCARを設定することによって、これらのリストの それぞれの要素が変更されます。次に例をあげます。

;; 一部分が共有された二つのリストを生成する。
(setq x1 '(a b c))
     => (a b c)
(setq x2 (cons 'z (cdr x1)))
     => (z b c)

;; 共有されたCARを変更する。
(setcar (cdr x1) 'foo)
     => foo
x1                           ; 両方のリストが変更される。
     => (a foo c)
x2
     => (z foo c)

;; 共有されていないCARを変更する。
(setcar x1 'baz)
     => baz
x1                           ; 片方のリストのみが変更される。
     => (baz foo c)
x2
     => (z foo c)

次は、変数x1x2にある二つのリストの間での共有構造を図示し たものです。なぜbを変更することで両方の変数が変更されるか を示しています。

次は同じ関係を示す、別の箱表記です。

リストのCDRの変更

CDRを変更する最も低水準のプリミティブはsetcdrです。

Function: setcdr cons object
この関数は、consのCDRをobjectに置き換えます。 objectの値を返します。

次は、あるリストのCDRを別のリストで置き換える例です。リストの最 初の要素以外の要素は取り除かれ、要素の異なる並びに置き換えられます。 最初の要素はリストのCARに格納され、CDRの一部ではないため、 変更されません。

(setq x '(1 2 3))
     => (1 2 3)
(setcdr x '(4))
     => (4)
x
     => (1 4)

リスト中のコンス・セルのCDRを変更することで、リストの中程の 要素を取り除くことができます。たとえばリスト(a b c)の2番目の 要素bを、最初のセルのCDRを変更することによって取り除 くことができます。

(setq x1 '(a b c))
     => (a b c)
(setcdr x1 (cdr (cdr x1)))
     => (c)
x1
     => (a c)

これは、結果の箱表記です。

要素bを持っていた2番目のコンス・セルは依然として存在し、その CARはbのままですが、このリストの一部分ではありません。

同様に新しい要素を挿入することは、CDRを変更することで容易に行うこ とができます。

(setq x1 '(a b c))
     => (a b c)
(setcdr x1 (cons 'd (cdr x1)))
     => (d b c)
x1
     => (a d b c)

次は、結果の箱表記です。

リストを再構成する関数

以下のものは、コンス・セルのCDRを変更することで、 "破壊的に" リストを並 び変える関数です。これらの関数が "破壊的" と呼ばれるのは、戻り値とな る新しいリストを生成するために引数として与えられたもとのリストを分解するか らです。

次節の関数delqは、破壊的なリスト操作のもう一つの例です。

Function: nconc &rest lists
この関数は、listsの全ての要素を含むリストを返します。 append (see section コンス・セルとリストの生成)と異なり、listsはコピーされ ません。そのかわり、listsのそれぞれの最後のCDR が次のリストを参照するように修正されます。listsの最後のものは変 更されません。たとえば、
(setq x '(1 2 3))
     => (1 2 3)
(nconc x '(4 5))
     => (1 2 3 4 5)
x
     => (1 2 3 4 5)

nconcの最後の引数自身は修正されないので、上記の例のように、 '(4 5)のような定数リストを用いるのは理にかなっています。同様な理 由で、最後の引数はリストである必要はありません。

(setq x '(1 2 3))
     => (1 2 3)
(nconc x 'z)
     => (1 2 3 . z)
x
     => (1 2 3 . z)

nconcの最後の引数以外の引数に、quoteされた定数リストを用いることは よく陥る落し穴です。これを行うと、実行するたびにプログラムが修正さ れてしまいます。次のようなことが起きます。

(defun add-foo (x)            ; その引数の先頭にfooを加える
  (nconc '(foo) x))           ;   関数を定義したい。

(symbol-function 'add-foo)
     => (lambda (x) (nconc (quote (foo)) x))

(setq xx (add-foo '(1 2)))    ; うまくゆくように見える。
     => (foo 1 2)
(setq xy (add-foo '(3 4)))    ; 何が起きたか?
     => (foo 1 2 3 4)
(eq xx xy)
     => t

(symbol-function 'add-foo)
     => (lambda (x) (nconc (quote (foo 1 2 3 4) x)))

Function: nreverse list

この関数は、listの要素の順序を逆にします。reverseと異 なり、nreverseはリストを構成するコンス・セルのCDRを ひっくり返し、引数を修正します。listの最後のコンス・セルであったもの は、結果のリストの最初のセルになります。

たとえば、

(setq x '(1 2 3 4))
     => (1 2 3 4)
x
     => (1 2 3 4)
(nreverse x)
     => (4 3 2 1)
;; 先頭だったセルは最後尾になっている。
x
     => (1)

普通、混乱を避けるため、nreverseの結果をもとのリストをもってい た同じ変数に代入しなおします。

(setq x (nreverse x))

次に、お得意の例で、(a b c)nreverseを図示します。

Function: sort list predicate
この関数は、listを安定的に(stably)並べ換え、並べ換えられたリスト を返します。もとのlistは破壊されます。要素をpredicate を用いて比較します。安定的な並べ換えとは、並べ換えキーが等しい場合は 相対的な順序が変わらない並べ換えのことです。この安定性は、異なる predicateを用いて、続けて並べ換えを行うときに重要です。

引数predicateは、二つの引数をとる関数でなければなりません。この関 数は、listの二つの要素を引数にして呼ばれます。昇順に並べ換えるた めには、predicateは最初の要素が2番目の要素より小さいときに tを、そうでないときにはnilを返さなければなりません。

sortが破壊的であるということは、CDRを書き換えて listを構成するコンス・セルを再構成するということです。非破壊的並 べ換え関数であれば、要素をある順序で並べ換えて格納する、新しい コンス・セルを生成します。もとのリストを破壊することなく並べ換えを行ない たいのなら、最初にcopy-sequenceを用いてコピーした後、並べ換えを行っ てください。

並べ換えは、listのコンス・セルのCARは変更しません。つまり、 もともと要素aを持っていたlistの中のコンス・セルは、並べ換 え後もaをそのCARに持っています。ただしCDRが変更 されるため、リストの中の位置は変わっています。たとえば、

(setq nums '(1 3 2 6 5 4 0))
     => (1 3 2 6 5 4 0)
(sort nums '<)
     => (0 1 2 3 4 5 6)
nums
     => (1 2 3 4 5 6)

numsのリストの中に0が含まれていないことに注目してください。 numsの指すコンス・セルは並び換えを行う前と同じですが、もはや リストの最初のコンス・セルではありません。変数が並び換えられたリスト全体 を持っていると考えてはなりません! そのかわりsortの結果を保存し てから使用してください。ほとんどの場合、結果をもとのリストを格納していた 変数へ再度格納します。

(setq nums (sort nums '<))

並び換えを行うその他の関数に関しては、See section 整列sortの有用な例は、section 説明文字列へのアクセスdocumentationを参照してください。

集合としてのリストの使用

リストは、順序を持たない数学的な集合を表わすことができます。ある値がリストの 中にある場合、その値が集合の要素であるとします。二つの集合の和集合を生 成するためには(同じ要素を2重にもつことを気にしないのであれば)、 appendを使用してください。集合のためのその他の便利な関数として、 memqdelqと、これらのequal版である memberdeleteがあります。

Common Lisp注意書き: Common Lispには集合の操作のために(要素が2重にな ることを避ける)関数unionintersectionがありますが、 GNU Emacs Lispはこれらを持っていません。必要であればLispを用いて作る ことができます。

Function: memq object list
この関数は、objectlistの要素であるかどうかを調べます。 もしそうであれば、memqobjectが最初に見つかったところ から始まるリストを返します。そうでなければnilを返します。 memq`q'という文字はリストの要素とobjectを比較す るときにeqを用いることを示します。たとえば、
(memq 'b '(a b c b a))
     => (b c b a)
(memq '(2) '((1) (2)))    ; (2)(2)eqではない。
     => nil

Function: delq object list
この関数はlistからobjecteqである全ての要素を 破壊的に取り除きます。delq`q'という文字はmemq と同様に、リストの要素とobjectを比較するときにeqを用いる ことを示します。

delqがリストの先頭から要素を取り除くときは、単純にリストを順に調 べていった後、これらの要素の後の部分のリストを返します。

(delq 'a '(a b c)) == (cdr '(a b c))

リストの中間の要素が取り除かれる場合はCDRの書き換えが行なわれます (see section リストのCDRの変更)。

(setq sample-list '(a b c (4)))
     => (a b c (4))
(delq 'a sample-list)
     => (b c (4))
sample-list
     => (a b c (4))
(delq 'c sample-list)
     => (a b (4))
sample-list
     => (a b (4))

(delq 'c sample-list)が3番目の要素を取り除くために sample-listを修正するのに対して、(delq 'a sample-list) は 何も取り除かないことに気をつけてください。後者は単により短いリストを返す だけです。引数listを持っていた変数が、その後、より少ない個数の要素 を持っているとも、まだ同じリストを持っているとも仮定してはいけません! そ の代わりに、delqの結果を保存し、それを用いてください。通常結果を もとのリストを格納していた変数へ再度格納します。

(setq flowers (delq 'rose flowers))

次の例では、delqが照合した(4)sample-listの中の(4)eqではありません。

(delq '(4) sample-list)
     => (a c (4))

次の二つの関数は、memqdelqに似ていますが、要素の比較 にeqの代わりにequalを使用します。これらはEmacsバー ジョン19で新たに追加されました。

Function: member object list
この関数memberは、equalを使ってobjectlistの要素を比較することで、 objectが要素であるかどうかを調べます。 もしそうであれば、memberは、objectが最初に見つかったと ころから始まるリストを返します。そうでなければnilを返します。

この関数とmemqを比較してください。

(member '(2) '((1) (2)))  ; (2)(2)equal。
     => ((2))
(memq '(2) '((1) (2)))    ; (2)(2)eqではない。
     => nil
;; 同じ内容の二つの文字列はequalである。
(member "foo" '("foo" "bar"))
     => ("foo" "bar")

Function: delete object list
この関数は、objectequalである全ての要素 を、listから 破壊的に取り除きます。memqmemberと対応するのと同様 に、この関数はdelqに対応します。memberと同様に、 objectと要素を比較するのにequalを用います。一致する要素 を見つけたときにはdelqと同様にその要素を取り除きます。たとえば、
(delete '(2) '((2) (1) (2)))
     => ((1))

Comman Lisp注意書き: GNU Emacs Lispの関数memberdeleteは、Common LispではなくMaclispに由来します。Common Lisp では要素の比較にequalを用いません。

変数に格納されたリストに要素を加える他の方法として、section 変数の値を変更する方法の関数add-to-listも参照してください。

連想リスト

連想リスト(association list) (略してalist)はキーから値 への関連を記憶します。連想リストは、連想子(association)と呼ぶコンス・ セルのリストです。それぞれのセルのCARはキー(key)であり、 そのCDRはそれに関連づけられた値、連想値(associated value)です。 (7)

次はalistの例です。pineというキーは、conesという値 に関連づけられます。oakというキーはacornsという値に関 連づけられます。さらにmapleというキーはseedsという値 に関連づけられます。

'((pine . cones)
  (oak . acorns)
  (maple . seeds))

alistの連想値およびキーは、どんなLispオブジェクトでも構いません。 たとえば、次のalistでは、シンボルaと数1が関連づけられ、 文字列"b"リスト(2 3)が関連づけられます。 つまり、(2 3)は、そのalist要素のCDRです。

((a . 1) ("b" 2 3))

連想値を、要素のCDRのCARに格納するようにalistを構成 するのが適切な場合もあります。次はその例です。

'((rose red) (lily white) (buttercup yellow))

ここで、redroseの連想値であるとみなします。この方 法の一つの利点は他の関連する情報を、他の項目のリストでさえ、 CDRのCDRの中に格納することが可能であることです。一つの欠点 は、ある値をもつ要素を探すためにrassq (次の項を参照)を使うことが できないことです。これらの制約が問題でない場合、そのalistに対して 一貫性を保つのであれば、どう選択するかは好みの問題です。

上で示した同じalistは、要素のCDRに連想値を持つとみなすことも できることに注意してください。その場合、roseの連想値は、リスト (red)になります。

連想リストは、新しい連想子をリストの先頭に簡単に加えることができるため、 連想リストを用いなければスタックを用いるような情報を記録するのに、しばし ば使用されます。ある与えられたキーに関連する値を連想リストから検索すると きで、複数の関連する連想子がある場合には、最初に見つかったものが返されま す。

Emacs Lispでは、連想リストのある要素がコンス・セルではなくともエラーに はなりません。alistに対する検索関数は、単にこれらの要素を無視する だけです。多くの他のLispの実装ではこのような場合はエラーが通知されます。

いくつかの点で、属性リスト(property list)が連想リストと類似しているこ とに気をつけてください。属性リストは、それぞれのキーがただ一回の み用いられる連想リストのように振舞います。属性リストと連想リストの比較 のためSee section 属性リスト

Function: assoc key alist
この関数は、alistの中のkeyを持つ最初の連想子を返します。 equalを用いてalistの要素とkeyを比較します (see section 等価述語)。alistの中に、keyequalであるCARを持つ連想子がない場合、nilを返しま す。
(setq trees '((pine . cones) (oak . acorns) (maple . seeds)))
     => ((pine . cones) (oak . acorns) (maple . seeds))
(assoc 'oak trees)
     => (oak . acorns)
(cdr (assoc 'oak trees))
     => acorns
(assoc 'birch trees)
     => nil

次はキーや値がシンボルではない別の例です。

(setq needles-per-cluster
      '((2 "Austrian Pine" "Red Pine")
        (3 "Pitch Pine")
        (5 "White Pine")))

(cdr (assoc 3 needles-per-cluster))
     => ("Pitch Pine")
(cdr (assoc 2 needles-per-cluster))
     => ("Austrian Pine" "Red Pine")

Function: rassoc value alist
この関数は、alistの中のvalueを値に持つ最初の連想子を返しま す。alistの中にvalueequalであるCDRを 持つものがない場合、nilを返します。

rassocは、それぞれのalistのCARの代わりに、CDR と比較することを除いて、assocに似ています。与えられた値に関連 するキーを探す "逆(reverse) assoc" と考えることができます。

Function: assq key alist
この関数は、alistの中のkeyを持つ最初の連想子を返す点で assocに似ていますが、equalのかわりにeqを用いて 比較を行ないます。alistの中にkeyeqである CARを持つものがない場合はassqnilを返します。 eqequalよりも高速であり、ほとんどのalistはキーと してシンボルを用いるため、この関数はassocよりもよく使われます。 See section 等価述語
(setq trees '((pine . cones) (oak . acorns) (maple . seeds)))
     => ((pine . cones) (oak . acorns) (maple . seeds))
(assq 'pine trees)
     => (pine . cones)

一方、assqは、キーがシンボルではないalistには通常不便な関数で す。

(setq leaves
      '(("simple leaves" . oak)
        ("compound leaves" . horsechestnut)))

(assq "simple leaves" leaves)
     => nil
(assoc "simple leaves" leaves)
     => ("simple leaves" . oak)

Function: rassq value alist
この関数は、alistの中のvalueの値を持つ最初の連想子を返しま す。alistの中にvaludeeqであるCDRを持つ ものがない場合、nilを返します。

rassqは、それぞれのalistのCARの代わりにCDRと 比較することを除いて、assqに似ています。与えられた値に関連する キーを探す "逆(reverse) assq" と考えることができます。

たとえば、

(setq trees '((pine . cones) (oak . acorns) (maple . seeds)))

(rassq 'acorns trees)
     => (oak . acorns)
(rassq 'spores trees)
     => nil

rassqは、要素のCDRのCARに格納された値を探すことはでき ないことに気をつけてください。

(setq colors '((rose red) (lily white) (buttercup yellow)))

(rassq 'white colors)
     => nil

この場合は、(lily white)という連想子のCDRは、white というシンボルではなく、(white)というリストです。次のように連 想子をドット対記法を用いて表現すれば、よりわかりやすくなります。

(lily white) == (lily . (white))

Function: copy-alist alist
この関数は、alistの2段の深さのコピー(two-level deep copy)を返し ます。それぞれの連想の新しい組を作るので、昔のalistを変更することなく 新しいalistの連想を変更することが可能となります。
(setq needles-per-cluster
      '((2 . ("Austrian Pine" "Red Pine"))
        (3 . ("Pitch Pine"))
        (5 . ("White Pine"))))
=>
((2 "Austrian Pine" "Red Pine")
 (3 "Pitch Pine")
 (5 "White Pine"))

(setq copy (copy-alist needles-per-cluster))
=>
((2 "Austrian Pine" "Red Pine")
 (3 "Pitch Pine")
 (5 "White Pine"))

(eq needles-per-cluster copy)
     => nil
(equal needles-per-cluster copy)
     => t
(eq (car needles-per-cluster) (car copy))
     => nil
(cdr (car (cdr needles-per-cluster)))
     => ("Pitch Pine")
(eq (cdr (car (cdr needles-per-cluster)))
    (cdr (car (cdr copy))))
     => t

この例は、copy-alistを使っておけば、あるコピーの連想を、 他に影響を与えることなく変更できることを示します。

(setcdr (assq 3 copy) '("Martian Vacuum Pine"))
(cdr (assq 3 needles-per-cluster))
     => ("Pitch Pine")


Go to the first, previous, next, last section, table of contents.