调用访问器函数
目标是用访问器设置类槽
访问器是一对函数。您可以通过 获取设置值的部分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"
使用带有 APPLY 的 SETF 来隐藏 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 被设计成动态和反射性的,以允许这些事情。