如何在 setf 地方执行一个函数
How to execute a function on setf place
我有一个包含一些符号和值的列表。目标是使用访问器设置 class 插槽,其符号由列表提供:
(defclass my-class ()
((attr :accessor attr)))
(let ((to-call '(attr "some-value"))
(obj (make-instance 'my-class)))
(setf `(,(car to-call) obj) (cadr to-call)))
我试过通过宏:
(defmacro call-accessor (to-call)
`(setf (,(car to-call) obj) "some-value"))
(let ((to-call '(attr "some-value"))
(obj (make-instance 'my-class)))
(call-accessor to-call))
这也失败了,因为 to-call
是一个符号而不是列表。
eval
不起作用,因为 to-call
是词法变量;
- 无法对宏执行
let
以为其提供列表;
- 我试过
with-slots
和 with-accessors
但问题仍然存在,因为它们也是宏。
- 我考虑过声明其他宏的宏,还有符号宏。
如何通过与我的列表中的符号对应的访问器设置插槽?
谢谢。
您可以使用 setf
of slot-value
,使用数据对中的插槽名称符号:
(let ((to-call '(attr "some-value")))
(setf (slot-value obj (first to-call)) (second to-call)))
然而,直接使用 slot-value
通常只在你争论对象内部时才有意义(比如初始化实例 methods/combinations;或者你可能正在研究某种序列化机制)。
如果不是这种情况,则您只是将该对象用作关联数据结构。我建议改用 alist、plist 或 hash-map。
我同意可能应该使用 hash-table
之类的替代结构。但是要扩展 关于 slot-value
的答案,工作代码很简单:
(setf (slot-value obj 'attr) "some-value")
调用存取函数
The goal is to setf the class slot with the accessor
访问器是一对函数。您可以通过FDEFINITION
获取设置值的部分。该函数的名称是一个列表 (SETF accessor-name )
。这是不寻常的:在这种情况下,Common Lisp 的函数名称不是符号,而是列表。
CL-USER 14 > (let ((to-call '(attr "some-value"))
(obj (make-instance 'my-class)))
(funcall (fdefinition `(setf ,(first to-call)))
(second to-call)
obj)
(describe obj))
#<MY-CLASS 40200614FB> is a MY-CLASS
ATTR "some-value"
使用函数call-accessor
:
CL-USER 25 > (let ((to-call '(attr "some-value"))
(obj (make-instance 'my-class)))
(flet ((call-accessor (obj to-call)
(funcall (fdefinition `(setf ,(first to-call)))
(second to-call)
obj)))
(call-accessor obj to-call)
(describe obj)))
#<MY-CLASS 402000220B> is a MY-CLASS
ATTR "some-value"
使用 SETF 和 APPLY 来隐藏 FDEFINITION 调用
要将 setf
与计算访问器一起使用,可能需要使用 apply
表单和自定义函数。
像 call-accessor
这样的东西自然是一个函数,因为它会进行运行时查找并获取值。如果访问器在 编译时.
已知,则尝试使用宏会更有用
CL-USER 23 > (let ((to-call '(attr "some-value"))
(obj (make-instance 'my-class)))
(flet (((setf my-setter) (new-value object accessor)
(funcall (fdefinition `(setf ,accessor))
new-value
obj)))
(flet ((call-accessor (obj to-call)
(setf (apply #'my-setter obj (list (first to-call)))
(second to-call))))
(call-accessor obj to-call)
(describe obj))))
#<MY-CLASS 40200009AB> is a MY-CLASS
ATTR "some-value"
数据结构的选择
我认为可以计算访问函数和类似函数。可能有一些用例。 CLOS 被设计成动态的和反射的以允许这些事情。
我有一个包含一些符号和值的列表。目标是使用访问器设置 class 插槽,其符号由列表提供:
(defclass my-class ()
((attr :accessor attr)))
(let ((to-call '(attr "some-value"))
(obj (make-instance 'my-class)))
(setf `(,(car to-call) obj) (cadr to-call)))
我试过通过宏:
(defmacro call-accessor (to-call)
`(setf (,(car to-call) obj) "some-value"))
(let ((to-call '(attr "some-value"))
(obj (make-instance 'my-class)))
(call-accessor to-call))
这也失败了,因为 to-call
是一个符号而不是列表。
eval
不起作用,因为to-call
是词法变量;- 无法对宏执行
let
以为其提供列表; - 我试过
with-slots
和with-accessors
但问题仍然存在,因为它们也是宏。 - 我考虑过声明其他宏的宏,还有符号宏。
如何通过与我的列表中的符号对应的访问器设置插槽?
谢谢。
您可以使用 setf
of slot-value
,使用数据对中的插槽名称符号:
(let ((to-call '(attr "some-value")))
(setf (slot-value obj (first to-call)) (second to-call)))
然而,直接使用 slot-value
通常只在你争论对象内部时才有意义(比如初始化实例 methods/combinations;或者你可能正在研究某种序列化机制)。
如果不是这种情况,则您只是将该对象用作关联数据结构。我建议改用 alist、plist 或 hash-map。
我同意可能应该使用 hash-table
之类的替代结构。但是要扩展 slot-value
的答案,工作代码很简单:
(setf (slot-value obj 'attr) "some-value")
调用存取函数
The goal is to setf the class slot with the accessor
访问器是一对函数。您可以通过FDEFINITION
获取设置值的部分。该函数的名称是一个列表 (SETF accessor-name )
。这是不寻常的:在这种情况下,Common Lisp 的函数名称不是符号,而是列表。
CL-USER 14 > (let ((to-call '(attr "some-value"))
(obj (make-instance 'my-class)))
(funcall (fdefinition `(setf ,(first to-call)))
(second to-call)
obj)
(describe obj))
#<MY-CLASS 40200614FB> is a MY-CLASS
ATTR "some-value"
使用函数call-accessor
:
CL-USER 25 > (let ((to-call '(attr "some-value"))
(obj (make-instance 'my-class)))
(flet ((call-accessor (obj to-call)
(funcall (fdefinition `(setf ,(first to-call)))
(second to-call)
obj)))
(call-accessor obj to-call)
(describe obj)))
#<MY-CLASS 402000220B> is a MY-CLASS
ATTR "some-value"
使用 SETF 和 APPLY 来隐藏 FDEFINITION 调用
要将 setf
与计算访问器一起使用,可能需要使用 apply
表单和自定义函数。
像 call-accessor
这样的东西自然是一个函数,因为它会进行运行时查找并获取值。如果访问器在 编译时.
CL-USER 23 > (let ((to-call '(attr "some-value"))
(obj (make-instance 'my-class)))
(flet (((setf my-setter) (new-value object accessor)
(funcall (fdefinition `(setf ,accessor))
new-value
obj)))
(flet ((call-accessor (obj to-call)
(setf (apply #'my-setter obj (list (first to-call)))
(second to-call))))
(call-accessor obj to-call)
(describe obj))))
#<MY-CLASS 40200009AB> is a MY-CLASS
ATTR "some-value"
数据结构的选择
我认为可以计算访问函数和类似函数。可能有一些用例。 CLOS 被设计成动态的和反射的以允许这些事情。