Lisp 如何在结构';当使用intern时,s访问器

Lisp 如何在结构';当使用intern时,s访问器,lisp,common-lisp,allegro-cl,Lisp,Common Lisp,Allegro Cl,我想根据某个变量设置结构的不同字段。我决定采用以下方法: 生成具有字段访问器名称的字符串: (setq my-string (format nil "STRUCT-ESTADISTICAS-NUM-~S" x)) 然后将intern与funcall一起使用: (funcall (intern my-string) *estadisticas*) 此调用返回结构字段的正确值,但如果我尝试setf修改此值,它会抱怨说: (setf (funcall(intern my-string) *esta

我想根据某个变量设置结构的不同字段。我决定采用以下方法:

生成具有字段访问器名称的字符串:

(setq my-string (format nil "STRUCT-ESTADISTICAS-NUM-~S" x))
然后将intern与funcall一起使用:

(funcall (intern my-string) *estadisticas*)
此调用返回结构字段的正确值,但如果我尝试
setf
修改此值,它会抱怨说:

(setf (funcall(intern my-string) *estadisticas*) 0)
Error: `(SETF FUNCALL)' is not fbound
我可以理解为什么它不起作用,但我找不到修改结构字段的方法。 有什么想法吗?
谢谢。

您希望通过其名称调用结构的writer函数,并且writer的名称是list
(setf访问器名称)
;所以

(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),

正如所料。

动机:

建筑是一个相对低水平的设施。”“速度”是一个重要的设计目标。该标准不支持通过writer函数进行间接寻址(如我所读)。今天,除非需要更好的结构效率(有时可以更快地读取和写入具有结构的插槽),否则使用CLO作为默认值

第一-风格:

不要使用实习生,使用FIND-SYMBOL。还要指定包,否则FIND-SYMBOL将使用运行时值*package*作为包

Second-defrastruct

如果我正确阅读了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访问器函数

一些常见的Lisp实现可能会提供writer函数作为ANSI CL的非标准扩展

可能的解决方案

a) 使用CLOS类,DEFCLASS做你想做的事情

b) 写作者自己的功能

(defun (setf foo-bar) (new-value struct)
   (setf (foo-bar struct) new-value))
现在:

以上就是工作原理

c) (SETF SLOT-VALUE)-某些实现的另一个非标准特性

在Common Lisp的某些实现中,这不仅适用于CLOS类,也适用于结构:

(setf (slot-value some-struct 'bar) 42)

我不确定Allegro CL是否支持这一点,但这很容易找到。

使用:(funcall(fdefinition(list'setf(intern“STRUCT-ESTADISTICAS-NUM-1”))0 ESTADISTICAS)我仍然得到:错误:`(setf STRUCT-ESTADISTICAS-NUM-1)`不是fbound不要使用intern。使用FIND-SYMBOL,可以检查是否找到了符号,还可以确保在正确的包中查找访问器。我认为这是非标准的。定义编写器函数不需要DEFSTRUCT。它是Emacs Lisp还是Common Lisp?在可能的解决方案b中,如果Lisp实现实际为结构插槽访问器生成setf函数,它可能会生成一个无限递归函数。
(setf (slot-value some-struct 'bar) 42)