5.5 修改列表变量

这些函数以及一个宏提供了便捷的方式来修改存储在变量中的列表。

Macro: push element listname

该宏会创建一个新列表,其 CARelementCDRlistname 所指定的列表,并将这个新列表保存到 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 访问列表元素

有两个函数可修改作为变量值的列表。

Function: add-to-list symbol element &optional append compare-fn

如果元素 element 尚未是变量 symbol 原有值中的成员,此函数会将 element 加到该值的前面,从而设置变量 symbol。 无论是否更新,函数都会返回最终的列表。调用此函数前,symbol 的值最好已经是一个列表。 add-to-list 使用 compare-fn 比较 element 与列表中已有的元素;如果 compare-fnnil,则使用 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)))
Function: add-to-ordered-list symbol element &optional order

该函数会将元素 element 插入到符号 symbol 对应变量的原有值(必须是一个列表)中由 order 指定的位置,以此更新该变量的值。若 element 已是列表的成员,则会根据 order 调整它在列表中的位置。成员关系通过 eq 函数进行检测。无论变量值是否被更新,该函数都会返回最终的列表。

参数 order 通常为数字(整数或浮点数),列表元素会按照非递减的数值顺序排序。

order 也可以被省略或设为 nil: 若 element 已有对应的数值排序序号,则其序号保持不变; 若 element 无数值排序序号,则不会为其分配序号。 没有数值排序序号的元素会被放置在列表末尾,且无特定排列顺序。

order 为其他任意值: 若 element 已有数值排序序号,则会移除该序号; 若 element 无数值排序序号,则效果等同于 order 设为 nil

参数 symbol 不会被隐式引用(quoted) :add-to-ordered-list 是普通函数,行为与 set 一致,而非 setq。必要时请自行为该参数添加引用符号。

排序信息存储在符号 symbollist-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                       ;; foo was changed.
     ⇒ (a c b e d)

emacs

Emacs

org-mode

Orgmode

Donations

打赏

Copyright

© 2025 Jasper Hsu

Creative Commons

Creative Commons

Attribute

Attribute

Noncommercial

Noncommercial

Share Alike

Share Alike