0

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))

==> NIL

しかし、これらのスロットに新しい値を書き込めないのはなぜですか? 私のトライアルデータのクラス定義は、スロットごとにアクセサ関数を作成すべきではありませんか?

;; 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).
4

2 に答える 2

5

アクセサは と呼ばれa-datumます。

読者:

CL-USER 9 > #'a-datum
#<STANDARD-GENERIC-FUNCTION A-DATUM 406000091C>

ライター:

CL-USER 10 > #'(setf a-datum)
#<STANDARD-GENERIC-FUNCTION (SETF A-DATUM) 422000958C>

funcallライター経由で呼び出したい場合は、上記の関数を呼び出す必要があります。

単純なフォームがある場合(setf (a-datum foo) 'bar))、これはマクロ展開時に解決する必要があります。

エラーメッセージは、それ#'(setf funcall)が未定義であることを示しています。したがって(setf (funcall ...) ...)、存在しません。

あなたの場合、ライター機能をどのように取得しますか?

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>

あなたの課題: 上記の関数の正しい引数は何ですか?

于 2014-06-20T20:47:34.060 に答える
2

Rainer Joswigs の答えは、現在のコードで設定できない理由の問題に対処しています。ただし、リーダー、ライター、またはアクセサーの名前がスロット名と同じでなければならない理由はないことに注意することも重要です。そのため、実際に取得したものがスロット名である場合は、それを使用する必要があります(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
于 2014-06-20T21:29:55.343 に答える