这些函数以及一个宏提供了便捷的方式来修改存储在变量中的列表。
该宏会创建一个新列表,其 CAR 为 element,CDR 为 listname 所指定的列表,并将这个新列表保存到 listname 中。在最简单的情况下,listname 是一个未加引号、指向列表的符号,此时该宏等价于 (setq listname (cons element listname))。
(setq l '(a b))
⇒ (a b)
(push 'c l)
⇒ (c a b)
l
⇒ (c a b)
更一般地,listname 可以是一个广义变量(Generalized Variable)。这种情况下,该宏等价于 (setf listname (cons element listname))。
See 广义变量。
关于从列表中移除首个元素的 pop 宏,see 访问列表元素。
有两个函数可修改作为变量值的列表。
如果元素 element 尚未是变量 symbol 原有值中的成员,此函数会将 element 加到该值的前面,从而设置变量 symbol。
无论是否更新,函数都会返回最终的列表。调用此函数前,symbol 的值最好已经是一个列表。
add-to-list 使用 compare-fn 比较 element 与列表中已有的元素;如果 compare-fn 为 nil,则使用 equal 进行比较。
通常情况下,如果添加 element,会将其加到 symbol 列表的头部;但如果可选参数 append 非空,则会加到尾部。
参数 symbol 不会被自动加引号;add-to-list 是一个普通函数,类似 set,而与 setq 不同。如果你需要,需自行给参数加引号。
此函数用于向配置变量添加元素,例如 load-path(see 库搜索)、image-load-path(see Defining Images)等。其代码中包含大量针对这类用途的特殊检查,并会输出相应警告。因此,我们不建议在 Lisp 程序中用它来构造任意列表;这种情况下请改用 push。See 修改列表变量。
当 symbol 指向词法变量时,不要使用此函数。
以下示例展示 add-to-list 的用法:
(setq foo '(a b))
⇒ (a b)
(add-to-list 'foo 'c) ;; Add c.
⇒ (c a b)
(add-to-list 'foo 'b) ;; No effect.
⇒ (c a b)
foo ;; foo was changed.
⇒ (c a b)
与 (add-to-list 'var value) 等价的表达式如下:
(if (member value var)
var
(setq var (cons value var)))
该函数会将元素 element 插入到符号 symbol 对应变量的原有值(必须是一个列表)中由 order 指定的位置,以此更新该变量的值。若 element 已是列表的成员,则会根据 order 调整它在列表中的位置。成员关系通过 eq 函数进行检测。无论变量值是否被更新,该函数都会返回最终的列表。
参数 order 通常为数字(整数或浮点数),列表元素会按照非递减的数值顺序排序。
order 也可以被省略或设为 nil:
若 element 已有对应的数值排序序号,则其序号保持不变;
若 element 无数值排序序号,则不会为其分配序号。
没有数值排序序号的元素会被放置在列表末尾,且无特定排列顺序。
若 order 为其他任意值:
若 element 已有数值排序序号,则会移除该序号;
若 element 无数值排序序号,则效果等同于 order 设为 nil。
参数 symbol 不会被隐式引用(quoted) :add-to-ordered-list 是普通函数,行为与 set 一致,而非 setq。必要时请自行为该参数添加引用符号。
排序信息存储在符号 symbol 的 list-order 属性对应的哈希表中。symbol 不能指向词法变量。
以下是展示 add-to-ordered-list 用法的示例场景:
(setq foo '()) ;; 初始化foo为空列表 ⇒ nil (add-to-ordered-list 'foo 'a 1) ;; 把a. 插入位置 1 ⇒ (a) (add-to-ordered-list 'foo 'c 3) ;; 把c插入位置 3(列表只有 1 个元素,位置 3 等价于末尾) ⇒ (a c) (add-to-ordered-list 'foo 'b 2) ;; 把b插入位置 2 ⇒ (a b c) (add-to-ordered-list 'foo 'b 4) ;; 把已存在的b移动到位置 4(末尾) ⇒ (a c b) (add-to-ordered-list 'foo 'd) ;; 无 position,把d追加到末尾 ⇒ (a c b d) (add-to-ordered-list 'foo 'e) ;; 无 position,把 e 追加到末尾。 ⇒ (a c b e d) ;; 因为d无明确位置,最大的已定义位置是 4(b),因此e被插入到位置 5 foo ;;foowas changed. ⇒ (a c b e d)