我有一个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))

==>
;Compiler warnings for "/Users/frank/Documents/NRL/Error/Patrolbot/Patrol Construction Notes & Testing.lisp" :
;   In an anonymous lambda form at position 123: Undefined function (SETF FUNCALL)
> Error: Undefined function (SETF FUNCALL) called with arguments (42 #<STANDARD-GENERIC-FUNCTION A-DATUM #x302001D1C5DF> #<TRIAL-DATA #x30200200D95D>) .
> While executing: #<Anonymous Function #x30200200EB7F>, in process Listener-2(5).

最佳答案

Rainer Joswigs's answer解决了为什么不能使用现有代码进行设置的问题不过,还需要注意的是,读卡器、写卡器或访问器的名称不必与插槽名称相同,所以如果您实际得到的是插槽名称,那么应该使用(setf slot-value)例如。,

(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

关于lisp - CLOS插槽访问器:读取但不写入,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24335054/

10-12 23:04