Lisp CLOS插槽访问器:读取但不写入

Lisp CLOS插槽访问器:读取但不写入,lisp,common-lisp,accessor,slot,clos,Lisp,Common Lisp,Accessor,Slot,Clos,我有一个CLOS对象插槽的名称列表: (DEFCLASS TRIAL-DATA (STANDARD-OBJECT) ((A-DATUM :ACCESSOR A-DATUM :INITARG :A-DATUM :INITFORM NIL) (BOTH-DATA :ACCESSOR BOTH-DATA :INITARG :BOTH-DATA :INITFORM 0) (CUMULATIVE-DATA :ACCESSOR CUMULATIVE-DATA :INITARG :CUMULA

我有一个CLOS对象插槽的名称列表:

(DEFCLASS TRIAL-DATA (STANDARD-OBJECT) 
 ((A-DATUM :ACCESSOR A-DATUM :INITARG :A-DATUM :INITFORM NIL) 
  (BOTH-DATA :ACCESSOR BOTH-DATA :INITARG :BOTH-DATA :INITFORM 0) 
  (CUMULATIVE-DATA :ACCESSOR CUMULATIVE-DATA :INITARG :CUMULATIVE-DATA :INITFORM NIL) 
  (NAME :ACCESSOR NAME :INITARG :NAME :INITFORM VALUE)))

(let* ((td (make-instance 'trial-data))
   (slot-lst (mapcar #'slot-definition-name (class-slots (class-of td)))))
我可以读取这些插槽的值:

(let* ((td (make-instance 'trial-data))
   (slot-lst (mapcar #'slot-definition-name (class-slots (class-of td)))))
(funcall (symbol-function (nth 0 slot-lst)) td))
=>零

但是为什么我不能向这些插槽写入新值呢?我的试用数据类定义不应该为每个插槽创建一个访问器函数吗

;; Should set the first slot, a-datum's, value to 42
(let* ((td (make-instance 'trial-data))
       (slot-lst (mapcar #'slot-definition-name (class-slots (class-of td)))))
    (setf (funcall (symbol-function (nth 0 slot-lst)) td) 42))
==>

;针对“/Users/frank/Documents/NRL/Error/Patrolbot/Patrol-Construction Notes&Testing.lisp”的编译器警告:
;   在位置123处的匿名lambda表单中:未定义函数(SETF FUNCALL)
>错误:使用参数(42###)调用未定义的函数(SETF FUNCALL)。
>执行时:#,进程内侦听器-2(5)。

存取器称为
a-datum

读者:

CL-USER 9 > #'a-datum
#<STANDARD-GENERIC-FUNCTION A-DATUM 406000091C>
您的任务:上述函数的正确参数是什么?

解决了为什么不能使用现有代码进行设置的问题。但是,还需要注意的是,读卡器、写卡器或访问器的名称没有理由必须与插槽名称相同,因此,如果实际得到的是插槽名称,则应使用
(setf slot value)
。例如:

(defclass foo ()
  ((bar :accessor getbar :initform 42)))

(defparameter *foo* (make-instance 'foo))
因此,您可以使用
(mapcar#'slot-definition-name(class slots(class of td))
(setf slot value)
以及按索引读取/写入slots数据。
CL-USER 10 > #'(setf a-datum)
#<STANDARD-GENERIC-FUNCTION (SETF A-DATUM) 422000958C>
CL-USER 11 > (fdefinition '(setf a-datum))
#<STANDARD-GENERIC-FUNCTION (SETF A-DATUM) 422000958C>

CL-USER 12 > (let ((name 'a-datum)) (fdefinition `(setf ,name)))
#<STANDARD-GENERIC-FUNCTION (SETF A-DATUM) 422000958C>
(defclass foo ()
  ((bar :accessor getbar :initform 42)))

(defparameter *foo* (make-instance 'foo))
;; neither of these work
(setf (bar *foo*) 34)
(funcall #'(setf bar) 34 *foo*)

(slot-value *foo* 'bar)
;=> 42

(setf (slot-value *foo* 'bar) 36)
;=> 26

(slot-value *foo* 'bar)
;=> 36