Почему общие функции не совпадают с функциями доступа?
Из того, что я прочитал, я понимаю, что функции Accessor в CLOS позволяют программисту получать и устанавливать переменные и генерируют обобщенную функцию с именем, которое было присвоено аксессору, для которого вам нужно определить различные методы. Я хочу знать, почему общие функции не работают так же, как функции доступа?
например
(defclass animal ()
((sound
:initarg :sound
:initform "no sound"
:accessor make-sound)))
Я могу просто определить
(defmethod (setf make-sound) ((the-animal animal) value)
(setf (slot-value the-animal 'sound) value))
но если бы я забрал аксессор и добавил
(defgeneric (setf make-sound) (the-animal value))
тогда я получаю ошибку, когда после выполнения следующего кода.
(setf (make-sound dog) "bark")
если я не переопределю обобщенную функцию и метод следующим образом
(defgeneric (setf make-sound) (value the-animal))
(defmethod (setf make-sound) (value (the-animal animal))
(setf (slot-value the-animal 'sound) value))
или выполнить
(setf (make-sound "bark") dog) ;this also works with the accessor
Мой вопрос: почему это происходит? Почему я не могу достичь того же результата с помощью универсальных функций?
1 ответ
defmethod
Форма создает универсальную функцию, если ее нет.
CL-USER 7 > (defclass animal ()
((sound
:initarg :sound
:initform "no sound")))
#<STANDARD-CLASS ANIMAL 40200ED09B>
Помните: новое значение стоит первым в функции SETF. Это определяется стандартом Common Lisp.
CL-USER 8 > (defmethod (setf make-sound) (value (the-animal animal))
(setf (slot-value the-animal 'sound) value))
#<STANDARD-METHOD (SETF MAKE-SOUND) NIL (T ANIMAL) 40200F098B>
CL-USER 9 > (let ((dog (make-instance 'animal)))
(setf (make-sound dog) "bark")
dog)
#<ANIMAL 402002187B>
CL-USER 10 > (slot-value * 'sound)
"bark"
Кажется, работает.
В defclass
:accessor
Параметр slot определяет, что он определяет метод считывателя, а также соответствующий метод setf с правильным списком параметров: сначала новое значение, затем экземпляр этого класса.