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)

列表的第一个元素 antelopehippopotamus 替换。

所以我们可以看到,setcar 并没有像 cons 那样向列表中添加新元素;它替换了 antelopehippopotamus;它改变了列表。