动机:
结构是一个相对低级的设施。“速度”是一个重要的设计目标。标准不支持通过编写器函数进行间接调用(正如我所读的那样)。今天,使用 CLOS 作为默认设置,除非需要更高的结构效率(有时可以更快地读取和写入具有结构的插槽)。
第一风格:
不要使用 INTERN,使用 FIND-SYMBOL。还要指定包,否则 FIND-SYMBOL 会使用 *package* 的运行时值作为包
第二 - DESTRUCT
如果我正确阅读了 ANSI CL 标准,那么 DEFSTRUCT 并不是像 DEFCLASS 那样为插槽创建写入函数。
CL-USER 24 > (defstruct foo bar baz)
FOO
CL-USER 25 > #'(setf foo-bar)
Error: Undefined function (SETF FOO-BAR) in form (FUNCTION (SETF FOO-BAR)).
因此,构造这样的名称 (SETF FOO-BAR) 并尝试为其查找函数将失败,因为 DEFSTRUCT 没有定义这样的函数。
用户代码 (setf (foo-bar some-struct) 42) 的工作原理是基于 DEFSTRUCT 提供的已定义的 SETF 扩展,而不是基于已定义的 SETF 访问器函数。
一些 Common Lisp 实现可能会提供编写器函数作为 ANSI CL 的非标准扩展。
可能的解决方案:
a) 使用 CLOS 类, DEFCLASS 做你想做的事
b) 自己编写 writer 函数
(defun (setf foo-bar) (new-value struct)
(setf (foo-bar struct) new-value))
现在:
(funcall (fdefinition '(setf foo-bar)) 300 *foo*)
上面然后工作。
c) (SETF SLOT-VALUE) - 一些实现的另一个非标准特性。
在 Common Lisp 的某些实现中,这不仅适用于 CLOS 类,也适用于结构:
(setf (slot-value some-struct 'bar) 42)
我不确定 Allegro CL 是否支持这一点,但这很容易找到。