12.8 修改变量值

修改变量值的常规方式是使用特殊形式 setq。如果你需要在运行时动态计算要操作的变量,则使用函数 set

Special Form: setq [symbol form]…

该特殊形式是最常用的变量赋值方式。每个 symbol 会被赋予一个新值,该值为对应 form 表达式的求值结果。符号的当前绑定会被修改。

setq 不会对 symbol 求值,而是直接设置你写出的符号。我们称这个参数是 自动引用(automatically quoted) 的。setq 中的 ‘q’ 代表 “quoted(引用)”。

setq 形式的值,等于最后一个 form 表达式的值。

(setq x (1+ 2))
     ⇒ 3
x                   ; x now has a global value.
     ⇒ 3
(let ((x 5))
  (setq x 6)        ; The local binding of x is set.
  x)
     ⇒ 6
x                   ; The global value is unchanged.
     ⇒ 3

需要注意的是,第一个 form 会先被求值,随后第一个 symbol 被赋值;接着第二个 form 被求值,然后第二个 symbol 被赋值,依此类推:

(setq x 10          ; Notice that x is set before
      y (1+ x))     ;   the value of y is computed.
     ⇒ 11
Function: set symbol value

该函数会将 value 存入 symbol 的值单元(value cell)中。由于它是一个函数而非特殊形式,程序会对 symbol 对应的表达式求值,以确定要赋值的符号。函数的返回值为 value

当动态变量绑定生效时(默认行为),除了「set 会对其 symbol 参数求值,而 setq 不会」这一点外,setsetq 的作用效果完全相同。但当变量为词法绑定时,set 会修改该变量的 动态(dynamic) 值,而 setq 会修改其当前的(词法)值。See Scoping 变量绑定的作用域规则

(set one 1)
error→ Symbol's value as variable is void: one
(set 'one 1)
     ⇒ 1
(set 'two 'one)
     ⇒ one
(set two 2)         ; two evaluates to symbol one.
     ⇒ 2
one                 ; So it is one that was set.
     ⇒ 2
(let ((one 1))      ; This binding of one is set,
  (set 'one 3)      ;   not the global value.
  one)
     ⇒ 3
one
     ⇒ 2

symbol 实际上并非符号,则会触发 wrong-type-argument 错误。

(set '(x y) 'z)
error→ Wrong type argument: symbolp, (x y)
Macro: setopt [symbol form]…

该宏的作用与 setq 类似(见上文),但专用于用户可配置项(user options)。此宏会调用自定义机制(Customize machinery)来设置变量(可指定多个)(see 定义自定义变量)。值得注意的是,setopt 会执行与该变量关联的设置函数(setter function)。例如,若你编写了如下代码:

(defcustom my-var 1
  "My var."
  :type 'number
  :set (lambda (var val)
         (set-default var val)
         (message "We set %s to %s" var val)))

那么下面的代码除了会把 my-var 设置为 ‘2’ 之外,还会输出一条提示信息:

(setopt my-var 2)

setopt 还会检查该值是否对这个用户可配置项有效。例如,若使用 setopt 将一个定义为 number 类型的用户可配置项设置为字符串,会触发错误。

defcustom 及相关的自定义命令(如 customize-variable)不同,setopt 适用于非交互式场景,尤其常用于用户的初始化文件(init file)中。因此,它不会记录变量的标准值、保存值和用户设定值,也不会将该变量标记为可保存到自定义文件(custom file)的候选项。 setopt 宏也可用于普通的非用户可配置项变量,但效率远低于 setq。该宏的主要使用场景是在用户的初始化文件中设置用户可配置项。


emacs

Emacs

org-mode

Orgmode

Donations

打赏

Copyright

© 2025 Jasper Hsu

Creative Commons

Creative Commons

Attribute

Attribute

Noncommercial

Noncommercial

Share Alike

Share Alike