我有一个包含一些符号和值的列表。我们的目标是与存取,其符号由列表提供给SETF类的插槽:
(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插槽?
谢谢。
调用存取函数
我们的目标是与访问到SETF类插槽
存取器是一个双功能。你可以得到这台通过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被设计为动态和反思,让这些东西。
您可以使用setf
的slot-value
,采用槽名称符号在你的数据对:
(let ((to-call '(attr "some-value")))
(setf (slot-value obj (first to-call)) (second to-call)))
然而,直接使用slot-value
通常唯一明智的,当你在对象内部争吵(如初始化实例方法/组合;或者你正在研究一些序列化机制)。
如果不是的话,你正在使用的对象只是作为一个关联数据结构。我建议使用ALIST,plist中,或哈希地图代替。
我认为,像hash-table
另一种结构可能应该使用。但为了扩大有关Svante's slot-value
答案,工作代码很简单:
(setf (slot-value obj 'attr) "some-value")