setcar 修改列表元素 ¶修改一个 cons 单元的 CAR 可以使用 setcar。当作用于列表时,setcar 会用另一个元素替换列表中的某个元素。
本函数将 object 存为 cons 的新 CAR,替换掉它之前的 CAR。换句话说,它修改 cons 的 CAR 槽,使其指向 object。函数返回值为 object。 示例:
(setq x (list 1 2))
⇒ (1 2)
(setcar x 4)
⇒ 4
x
⇒ (4 2)
当一个 cons 单元是多个列表共享结构的一部分时,给该 cons 设置新的 CAR 会同时改变这些列表的对应元素。示例如下:
;; 创建两个存在部分共享的列表
(setq x1 (list '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 会同时改变两个列表:
--- --- --- --- --- ---
x1---> | | |----> | | |--> | | |--> nil
--- --- --- --- --- ---
| --> | |
| | | |
--> a | --> b --> c
|
--- --- |
x2--> | | |--
--- ---
|
|
--> z
下面是另一种方框图示形式,表示同样的关系:
x1:
-------------- -------------- --------------
| car | cdr | | car | cdr | | car | cdr |
| a | o------->| b | o------->| c | nil |
| | | -->| | | | | |
-------------- | -------------- --------------
|
x2: |
-------------- |
| car | cdr | |
| z | o----
| | |
--------------