CDRを変更するもっとも低レベルのプリミティブ関数はsetcdr
です:
この関数は前のCDRを置き換えて、consの新しいCDRにobjectを格納する。言い換えると、この関数はconsのCDRがobjectを参照するように変更する。この関数は値objectをリターンする。
以下はリストのCDRを、他のリストに置き換える例です。1番目の要素以外のすべての要素は、別のシーケンスまたは要素のために取り除かれます。1番目の要素はリストのCARなので変更されず、CDRを通じて到達することもできないからです。
(setq x (list 1 2 3)) ⇒ (1 2 3)
(setcdr x '(4)) ⇒ (4)
x ⇒ (1 4)
リスト内のコンスセルのCDRを変更することにより、リストの途中から要素を削除できます。たとえば以下では、1番目のコンスセルのCDRを変更することにより、2番目の要素b
をリスト(a
b c)
から削除します。
(setq x1 (list 'a 'b 'c)) ⇒ (a b c) (setcdr x1 (cdr (cdr x1))) ⇒ (c) x1 ⇒ (a c)
以下に結果をボックス表記で示します:
-------------------- | | -------------- | -------------- | -------------- | car | cdr | | | car | cdr | -->| car | cdr | | a | o----- | b | o-------->| c | nil | | | | | | | | | | -------------- -------------- --------------
以前は要素b
を保持していた2番目のコンスセルは依然として存在し、そのCARもb
のままですが、すでにこのリストの一部を形成していません。
CDRを変更して新しい要素を挿入するのも同じくらい簡単です:
(setq x1 (list 'a 'b 'c)) ⇒ (a b c) (setcdr x1 (cons 'd (cdr x1))) ⇒ (d b c) x1 ⇒ (a d b c)
以下に結果をボックス表記で示します:
-------------- ------------- ------------- | car | cdr | | car | cdr | | car | cdr | | a | o | -->| b | o------->| c | nil | | | | | | | | | | | | --------- | -- | ------------- ------------- | | ----- -------- | | | --------------- | | | car | cdr | | -->| d | o------ | | | ---------------