検索エンジンから来た人に注意このマニュアルは、Emacs ver. 19.x 向けのマニュアルを Mule 2.x の開発にあたり邦訳したものを、 電脳外道学会がミラーリングしているものであり、旧版製品パラノイアであるところの椅子人の趣味によるものです。しかしながら、現在の Emacs の主流は ver. 20 以降であり、ver 19.x と ver 20.x とでは、仕様の違いが少なからずあります。 したがって、一般的な Emacs ユーザーにとっては、
このマニュアルと実機の動作とが符合しない場合があります。
|
リスト(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
であるかを調べる
ために用いられます(これらの述語の多くは、他のものを用いて定義できますが、
非常によく使われるので、全部を用意しておくことに意味があるのです)。
t
を返し、そうでな
ければnil
を返します。nil
はリストですが、コンス・
セルではありません。
t
を返し、そうでなけれ
ばnil
を返します。コンス・セル以外の全てのオブジェクトはアトムで
す。nil
はアトムであり、かつリストでもあります。アトムであり、
かつリストであるのは、唯一nil
だけです。
(atom object) == (not (consp object))
nil
であれば
t
を返し、そうでなければnil
を返します。
(listp '(1)) => t (listp '()) => t
listp
の反対の働きをします。つまりobjectが
リストでなければt
を返し、そうでなければnil
を返します。
(listp object) == (not (nlistp object))
nil
であればt
を返し、そうで
なければnil
を返します。この関数はnot
と同じものですが、
わかりやすいように、objectがリストである場合null
を、
真か偽かを表わす場合にはnot
を用います(section 条件を結合するための構文要素のnot
を参照)。
(null '(1)) => nil (null '()) => t
特別な場合として、cons-cellがnil
の場合、car
は
nil
を返すと定義されます。したがって、いかなるリストもcar
の有効な引数となります。引数がコンス・セルでもnil
でもない場
合、エラーが通知されます。
(car '(a b c)) => a (car '()) => nil
特別な場合として、cons-cellがnil
の場合、cdr
は
nil
を返すと定義されます。したがって、いかなるリストもcdr
の
有効な引数となります。引数がコンス・セルでもnil
でもない場合、エラー
が通知されます。
(cdr '(a b c)) => (b c) (cdr '()) => nil
nil
を返します。
これは、objectがリストでない場合にエラーを通知するcar
と
対照的です。
(car-safe object) == (let ((x object)) (if (consp x) (car x) nil))
nil
を返します。
これは、objectがリストでない場合にエラーを通知するcdr
と
対照的です。
(cdr-safe object) == (let ((x object)) (if (consp x) (cdr x) nil))
nth
はnil
を
返します。
nが負である場合、nth
はlistの最初の要素を返
します。
(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))
nが0以下の場合、nthcdr
はlist全体を返しま
す。listの長さがn以下の場合は、nthcdr
は
nil
を返します。
(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
の方が多
く使われています。
(cons 1 '(2)) => (1 2) (cons 1 '()) => (1) (cons 1 2) => (1 . 2)
cons
は、しばしばリストの先頭に新しい要素を加えるために用いられます。
これを要素をリストにconsするといいます。たとえば、
(setq list (cons newelt list))
この例で用いられたlist
という変数と、次に説明するlist
という関数との間で衝突が起きないことに注意してください。いかなるシンボ
ルも変数名、関数名、両方の目的に使うことができます。
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
make-list
とmake-string
を比
較してください(see section 文字列の生成)。
(make-list 3 'pigs) => (pigs pigs pigs) (make-list 0 'pigs) => nil
もっと一般化していえば、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)
append
にsequencesが与えられなかった場合、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 文字と文字列間の変換)を用いることです。
(setq x '(1 2 3 4)) => (1 2 3 4) (reverse x) => (4 3 2 1) x => (1 2 3 4)
setcar
とsetcdr
というプリミティブを用いて、コンス・セルの
CARとCDRの内容を変更することができます。
Common Lisp注意書き: Common Lispには、リスト構造を変更する関数
rplaca
とrplacd
があります。これらはsetcar
やsetcdr
と同様な処理を行ないますが、setcar
やsetcdr
が新たなCARやCDRの値を返すのに対してCommon Lispの関数は コンス・セルを返します。
setcar
によるリスト要素の変更
setcar
によって、コンス・セルのCARの変更が行なわれます。リスト
に対して用いられた場合、setcar
は、リストのある要素を別の要素で置
き換えます。
(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)
次は、変数x1
とx2
にある二つのリストの間での共有構造を図示し
たものです。なぜb
を変更することで両方の変数が変更されるか
を示しています。
次は同じ関係を示す、別の箱表記です。
CDRを変更する最も低水準のプリミティブはsetcdr
です。
次は、あるリストの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
は、破壊的なリスト操作のもう一つの例です。
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)))
この関数は、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
を図示します。
引数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
を使用してください。集合のためのその他の便利な関数として、
memq
とdelq
と、これらのequal
版である
member
とdelete
があります。
Common Lisp注意書き: Common Lispには集合の操作のために(要素が2重にな ることを避ける)関数
union
とintersection
がありますが、 GNU Emacs Lispはこれらを持っていません。必要であればLispを用いて作る ことができます。
memq
はobjectが最初に見つかったところ
から始まるリストを返します。そうでなければnil
を返します。
memq
の`q'という文字はリストの要素とobjectを比較す
るときにeq
を用いることを示します。たとえば、
(memq 'b '(a b c b a)) => (b c b a) (memq '(2) '((1) (2))) ;(2)
と(2)
はeq
ではない。 => nil
eq
である全ての要素を
破壊的に取り除きます。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))
次の二つの関数は、memq
とdelq
に似ていますが、要素の比較
にeq
の代わりにequal
を使用します。これらはEmacsバー
ジョン19で新たに追加されました。
member
は、equal
を使ってobjectと
listの要素を比較することで、
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")
equal
である全ての要素
を、listから
破壊的に取り除きます。memq
がmember
と対応するのと同様
に、この関数はdelq
に対応します。member
と同様に、
objectと要素を比較するのにequal
を用います。一致する要素
を見つけたときにはdelq
と同様にその要素を取り除きます。たとえば、
(delete '(2) '((2) (1) (2))) => ((1))
Comman Lisp注意書き: GNU Emacs Lispの関数
member
とdelete
は、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))
ここで、red
はrose
の連想値であるとみなします。この方
法の一つの利点は他の関連する情報を、他の項目のリストでさえ、
CDRのCDRの中に格納することが可能であることです。一つの欠点
は、ある値をもつ要素を探すためにrassq
(次の項を参照)を使うことが
できないことです。これらの制約が問題でない場合、そのalistに対して
一貫性を保つのであれば、どう選択するかは好みの問題です。
上で示した同じalistは、要素のCDRに連想値を持つとみなすことも
できることに注意してください。その場合、rose
の連想値は、リスト
(red)
になります。
連想リストは、新しい連想子をリストの先頭に簡単に加えることができるため、 連想リストを用いなければスタックを用いるような情報を記録するのに、しばし ば使用されます。ある与えられたキーに関連する値を連想リストから検索すると きで、複数の関連する連想子がある場合には、最初に見つかったものが返されま す。
Emacs Lispでは、連想リストのある要素がコンス・セルではなくともエラーに はなりません。alistに対する検索関数は、単にこれらの要素を無視する だけです。多くの他のLispの実装ではこのような場合はエラーが通知されます。
いくつかの点で、属性リスト(property list)が連想リストと類似しているこ とに気をつけてください。属性リストは、それぞれのキーがただ一回の み用いられる連想リストのように振舞います。属性リストと連想リストの比較 のためSee section 属性リスト。
equal
を用いてalistの要素とkeyを比較します
(see section 等価述語)。alistの中に、keyと
equal
である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")
equal
であるCDRを
持つものがない場合、nil
を返します。
rassoc
は、それぞれのalistのCARの代わりに、CDR
と比較することを除いて、assoc
に似ています。与えられた値に関連
するキーを探す "逆(reverse) assoc
" と考えることができます。
assoc
に似ていますが、equal
のかわりにeq
を用いて
比較を行ないます。alistの中にkeyとeq
である
CARを持つものがない場合はassq
はnil
を返します。
eq
はequal
よりも高速であり、ほとんどの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)
eq
である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))
(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.