7.5 setcar

从名称不难猜到,setcarsetcdr 函数用于将列表的 CARCDR 设置为新值。它们会真正修改原列表,这与 carcdr 保留原列表不变的行为不同。想要理解其工作方式,最好的方法是动手实验。我们先从 setcar 开始。

首先,可以创建一个列表,并用 setq 特殊形式将其赋值给变量。因为我们打算用 setcar 修改这个列表,所以这个 setq 不应使用引用形式 '(antelope giraffe lion tiger),否则得到的列表会是程序的一部分,运行时尝试修改程序片段可能导致异常。通常来说,Emacs Lisp 程序的组成部分在运行时应是常量(不可修改)。因此我们改用 list 函数构造动物列表,写法如下:

(setq animals (list 'antelope 'giraffe 'lion 'tiger))

如果你正在 GNU Emacs 的 Info 中阅读本文,可以照常执行该表达式:将光标移到表达式末尾并按 C-x C-e。(我写这段内容时也正在这样操作。这也是将解释器内置在运行环境中的优势之一。顺便一提,如果最后一个括号后面没有注释等内容,光标可以放在下一行。也就是说,即使光标位于下一行的第一列,也无需移动。实际上,Emacs 允许最后一个括号后有任意数量的空白字符。)

当我们对变量 animals 求值时,可以看到它绑定到列表 (antelope giraffe lion tiger)

animals
     ⇒ (antelope giraffe lion tiger)

换句话说,变量 animals 指向列表 (antelope giraffe lion tiger)

接下来,执行 setcar 函数并传入两个参数:变量 animals 和被引用的符号 hippopotamus;只需写出三元素列表 (setcar animals 'hippopotamus) 并照常执行即可:

(setcar animals 'hippopotamus)

执行该表达式后,再次对变量 animals 求值,你会发现动物列表已经改变:

animals
     ⇒ (hippopotamus giraffe lion tiger)

列表的第一个元素 antelope 被替换成了 hippopotamus

由此可见,setcar 并不会像 cons 那样向列表添加新元素,而是将 antelope 替换为 hippopotamus — 它 修改 了列表。