使用实习生时,如何在结构登录机上进行setF
-
30-09-2019 - |
题
我想 setf
结构的不同字段取决于某个变量。我决定使用以下方法:
使用该字段的登录名来生成字符串:
(setq my-string (format nil "STRUCT-ESTADISTICAS-NUM-~S" x))
然后将实习生与Funcall一起使用:
(funcall (intern my-string) *estadisticas*)
此呼叫返回结构字段的正确值,但是如果我尝试 setf
要修改此值,它抱怨说:
(setf (funcall(intern my-string) *estadisticas*) 0)
Error: `(SETF FUNCALL)' is not fbound
我可以理解为什么它不起作用,但是我找不到修改结构字段的方法。任何的想法?谢谢你。
解决方案
您想通过其名称来调用结构的作者函数,而作者的名称是列表 (setf accessor-name)
;所以
(funcall (fdefinition (list 'setf (intern my-string))) 0 estadisticas)
编辑:
看不到其余的代码,很难理解出了什么问题。在SBCL上,这对我有用:
(defstruct point x y)
(let ((point (make-point :x 1 :y 2)))
(funcall (fdefinition (list 'setf (intern "POINT-X"))) 10 point)
point)
以上评估
#S(POINT :X 10 :Y 2),
正如预期的。
其他提示
动机:
结构是一个相对较低的设施。 “速度”是一个重要的设计目标。标准不支持通过作者函数的间接功能(正如我阅读的那样)。今天,将CLOS用作默认值,除非需要更好的结构效率(有时可以更快地阅读和用结构写入插槽)。
首先 - 样式:
不要使用实习生,请使用Find-Mbol。还指定软件包,否则Find-Mbol将使用 *软件包 *的运行时值作为软件包
第二-Defstruct
如果我正确读取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)并试图找到一个函数将失败,因为删除未定义此类函数。
在用户代码(setf(foo-bar some-scruct)42)中,作品是基于DefStruct提供的定义SETF扩展,但不基于定义的SETF访问器函数。
一些常见的LISP实现可能会提供作者功能作为ANSI CL的非标准扩展。
可能的解决方案:
a)使用关闭类,DefClass做您想要的
b)自己写作者的功能
(defun (setf foo-bar) (new-value struct)
(setf (foo-bar struct) new-value))
现在:
(funcall (fdefinition '(setf foo-bar)) 300 *foo*)
上面有效。
c)(SETF插槽值) - 某些实现的另一个非标准功能。
在普通LISP的某些实现中,这不仅适用于关闭类,而且适用于结构:
(setf (slot-value some-struct 'bar) 42)
我不确定Allegro CL是否确实支持了这一点,但这很容易找到。