Создать полиномиальный объект из числа, используя change-class - PullRequest
2 голосов
/ 28 марта 2010

Я написал полиномиальный класс по линиям, описанным в 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)

Я собираюсь реализовать преобразование вручную, но я бы предпочел использовать встроенные средства clos.

Как указывает Ксах, я мог использовать принуждение или плавание, чтобы изменить 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]

Ответы [ 2 ]

2 голосов
/ 28 марта 2010

Вы можете использовать COERCE или FLOAT, чтобы сделать это:

(float 4) => 4.0
(coerce 4 'float) => 4.0
1 голос
/ 29 марта 2010

Вы не можете использовать CHANGE-CLASS с числами. Числа не являются экземплярами классов CLOS. Также считается, что CHANGE-CLASS деструктивно изменяет экземпляр на новый класс, не изменяя идентификацию исходного экземпляра.

Я бы либо:

  • добавить методы в CHANGE-CLASS, которые делают то, что вы хотите

  • или напишите функцию CHANGE, которая реализует различные пользовательские правила приведения и вызывает CHANGE-CLASS для любого изменения одного класса CLOS на другой класс CLOS.

...