使用 intern 时如何对结构的访问器执行 setf

发布于 2024-09-17 08:07:49 字数 501 浏览 2 评论 0原文

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

使用字段的访问器名称生成字符串:

(setq my-string (format nil "STRUCT-ESTADISTICAS-NUM-~S" x))

然后将 intern 与 funcall 一起使用:

(funcall (intern my-string) *estadisticas*)

此调用返回结构体字段的正确值,但如果我尝试 setf 修改此值value 它抱怨说:

(setf (funcall(intern my-string) *estadisticas*) 0)
Error: `(SETF FUNCALL)' is not fbound

我可以理解为什么它不起作用,但我找不到修改结构体字段的方法。 有什么想法吗? 谢谢。

I'd like to setf different fields of a struct depending on a certain variable. I decided to use the following approach:

Generate a string with the field's accessor name:

(setq my-string (format nil "STRUCT-ESTADISTICAS-NUM-~S" x))

and then use intern with funcall:

(funcall (intern my-string) *estadisticas*)

This call returns the correct value of the struct's field, but if I try setf to modify this value it complains saying:

(setf (funcall(intern my-string) *estadisticas*) 0)
Error: `(SETF FUNCALL)' is not fbound

I can understand why it doesn't work, but I can't find a way to modify the struct's fields.
Any idea?
Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

滥情哥ㄟ 2024-09-24 08:07:49

您想通过结构体的名称调用该结构体的编写器函数,编写器的名称是列表(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),

符合预期。

You want to call a writer function of the struct via its name, and the name of the writer is the list (setf accessor-name); so

(funcall (fdefinition (list 'setf (intern my-string))) 0 estadisticas)

Edit:

Not seeing the rest of your code, it's hard to fathom what went wrong. On SBCL this works for me:

(defstruct point x y)
(let ((point (make-point :x 1 :y 2)))
  (funcall (fdefinition (list 'setf (intern "POINT-X"))) 10 point)
  point)

The above evaluates to

#S(POINT :X 10 :Y 2),

as expected.

酷炫老祖宗 2024-09-24 08:07:49

动机:

结构是一种相对较低级别的设施。 “速度”是一个重要的设计目标。标准不支持通过编写器函数间接进行(据我所知)。今天,使用 CLOS 作为默认值,除非需要更高的结构效率(有时可以更快地读写带有结构的槽)。

第一种风格:

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

第二-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) 并尝试为其查找函数将会失败,因为 DEFSTRUCT 没有定义这样的函数。

用户代码 (setf (foo-bar some-struct) 42) 中的工作原理是基于 DEFSTRUCT 提供的定义的 SETF 扩展,而不是基于定义的 SETF 访问器函数。

一些 Common Lisp 实现可能会提供编写器函数作为 ANSI CL 的非标准扩展。

可能的解决方案

a) 使用 CLOS 类,DEFCLASS 执行您想要的操作

b) 自己编写编写器函数

(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 是否支持这一点,但这很容易找到。

Motivation:

Structures are a relatively low-level facility. 'Speed' was an important design goal. Indirection via writer functions is not supported by the standard (as I read it). Today, use CLOS as the default, unless one needs better efficiency of structures (faster read and writes of slots with structures are sometimes possible).

First - style:

Don't use INTERN, use FIND-SYMBOL. Also specify the package, otherwise FIND-SYMBOL will use the runtime value of *package* as the package

Second - DEFSTRUCT

If I read the ANSI CL standard correctly, it is not that DEFSTRUCT creates writer functions for slots like DEFCLASS does.

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)).

So, constructing such a name (SETF FOO-BAR) and trying to find a function for that will fail, since there is no such function defined by the DEFSTRUCT.

That in user code (setf (foo-bar some-struct) 42) works, is based on defined SETF expansions provided by DEFSTRUCT, but not on defined SETF accessor functions.

Some Common Lisp implementations may provide writer functions as a non-standard extension to ANSI CL.

Possible solutions:

a) use CLOS classes, DEFCLASS does what you want

b) write the writer functions yourself

(defun (setf foo-bar) (new-value struct)
   (setf (foo-bar struct) new-value))

Now:

(funcall (fdefinition '(setf foo-bar)) 300 *foo*)

Above then works.

c) (SETF SLOT-VALUE) - another non-standard feature of some implementations.

In some implementations of Common Lisp this works not only for CLOS classes, but also for structures:

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

I'm not sure if Allegro CL does support that, but that would be easy to find out.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文