Создайте полиномиальный объект из числа, используя класс изменения.
-
22-09-2019 - |
Вопрос
Я написал полиномиальный класс по принципу, описанному в SICP 2.5.3 (кроме использования defclass).Я хотел бы иметь возможность беспрепятственно складывать и умножать полиномы и обычные числа, но я не могу заставить класс изменений принимать число.
Я попытался упростить проблему, изменив класс с целого числа на число с плавающей запятой:
(change-class 4 'float)
но это дало мне ошибку:
There is no applicable method for the generic function
#<STANDARD-GENERIC-FUNCTION CHANGE-CLASS (7)>
when called with arguments
(4 #<BUILT-IN-CLASS FLOAT>).
[Condition of type SIMPLE-ERROR]
Я получаю ошибку той же формы от (к вашему сведению):
(change-class 4 'polynomial)
Я собираюсь реализовать преобразование вручную, но предпочитаю использовать встроенные средства закрытия.
Как указывает Ксач, я мог бы использовать принуждение или плавающее число, чтобы изменить 4 на число с плавающей запятой.Это было задумано как более простой пример того, что я пытался сделать, и исключить любую возможность того, что мой экземпляр обновления для другого класса будет неправильным.
Вот более длинная версия того, что я пробовал, но это не сработало:
(defclass polynomial ()
((var :accessor var :initarg :var :initform 'x)
(terms :accessor terms :initarg :terms :initform (make-empty-term-list))))
(defmethod update-instance-for-different-class :before ((old number)
(new polynomial)
&key)
(setf (slot-value new 'terms) (adjoin-term (make-term old 0)
(make-empty-term-list))))
(change-class 4 'polynomial)
Я все еще получаю сообщение об ошибке, как в примере выше:
There is no applicable method for the generic function
#<STANDARD-GENERIC-FUNCTION CHANGE-CLASS (7)>
when called with arguments
(4 #<STANDARD-CLASS POLYNOMIAL>).
[Condition of type SIMPLE-ERROR]
Решение
Вы не можете использовать CHANGE-CLASS с числами.Числа не являются экземплярами классов CLOS.СМЕНА КЛАССА также считается разрушительно изменить экземпляр на новый класс, не меняя идентичность исходного экземпляра.
Я бы либо:
добавьте методы в CHANGE-CLASS, которые делают то, что вы хотите
или напишите функцию CHANGE, которая реализует различные пользовательские правила приведения и вызывает CHANGE-CLASS для любого изменения одного класса CLOS на другой класс CLOS.
Другие советы
Для этого вы можете использовать COERCE или FLOAT:
(float 4) => 4.0
(coerce 4 'float) => 4.0