修改 CDR 最底层的原语是 setcdr:
该函数将 object 存为 cons 的新 CDR,替换掉它原先的 CDR。换句话说,它修改 cons 的 CDR 槽位,使其指向 object。函数返回值为 object。
下面是一个用另一个列表替换列表 CDR 的示例。列表中除第一个元素外的所有元素都被移除,替换为另一组元素。第一个元素保持不变,因为它存放在列表的 CDR 中,不会通过 CDR 被访问到。
(setq x (list 1 2 3))
⇒ (1 2 3)
(setcdr x '(4))
⇒ (4)
x
⇒ (1 4)
通过修改列表中 cons 单元的 CDR,可以从列表中间删除元素。例如,我们通过修改第一个 cons 单元的 CDR,从列表 (a b c) 中删除第二个元素 b:
(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 的第二个 cons 单元仍然存在,它的 CDR 仍然是 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------
| | |
---------------