12.17.1 setf

setf 宏是操作广义变量最基础的方式。setf 表达式与 setq 类似, 不同之处在于:它允许每一对参数的第一个(左侧)参数是任意合法的位置形式,而非仅能使用符号。 例如,(setf (car a) b) 会将 a 的 car 部分设为 b,其执行效果与 (setcar a b) 完全一致,但无需为这类位置的赋值和读取操作分别使用两个不同的函数。

Macro: setf [place form]…

该宏会对 form(表达式)进行求值,并将求值结果存储到 place(位置)中, 其中 place 必须是合法的广义变量形式。若传入多组 placeform 配对参数, 赋值操作会像 setq 一样按顺序执行。setf 的返回值为最后一个 form 的求值结果。

以下 Lisp 表达式是 Emacs 中可作为广义变量使用的形式,因此可出现在 setfplace 参数中:

若传入的 place(位置)形式是 setf 无法处理的类型,setf 会触发错误。

需要注意的是,对于 nthcdr 而言,该函数的列表参数本身必须是合法的 place(位置)形式。 例如,(setf (nthcdr 0 foo) 7) 会将 foo 本身赋值为 7。

push(see 修改列表变量)和 pop(see 访问列表元素) 可操作广义变量,而非仅能操作列表。(pop place) 会移除并返回存储在 place 中的列表的第一个元素, 其功能类似于 (prog1 (car place) (setf place (cdr place))), 区别在于它会确保所有子表达式仅求值一次。 (push x place) 会将 x 插入到存储在 place 中的列表的头部, 其功能类似于 (setf place (cons x place)),差异同样体现在子表达式的求值逻辑上。 需注意,在 nthcdr 类型的位置上使用 pushpop, 可实现在列表任意位置插入或删除元素。

cl-lib 库为广义变量定义了多种扩展功能,包括新增的 setf 位置形式。 See Generalized Variables in Common Lisp Extensions, Common Lisp 扩展


emacs

Emacs

org-mode

Orgmode

Donations

打赏

Copyright

© 2025 Jasper Hsu

Creative Commons

Creative Commons

Attribute

Attribute

Noncommercial

Noncommercial

Share Alike

Share Alike