Создайте полиномиальный объект из числа, используя класс изменения

Я написал полиномиальный класс в соответствии со строками, описанными в 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]

Я получаю сообщение об ошибке той же формы от (fyi):

(change-class 4 'polynomial)

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

Как указывает Xach, я мог бы использовать coerce или float, чтобы изменить 4 на float. Это было задумано как более простой пример того, что я пытался сделать, и исключить любую возможность того, что мой экземпляр обновления для другого класса неверен.

Вот более длинная версия того, что я пробовал, но это не сработало:

(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]

person charlieb    schedule 28.03.2010    source источник


Ответы (2)


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

Я бы либо:

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

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

person Rainer Joswig    schedule 28.03.2010
comment
Спасибо, кажется, я сбит с толку, потому что я помню, что cl - это объекты до конца, но, возможно, это не CLOS до конца. Я только что проверил гиперспец и он говорит, что о t что 2. имя типа, к которому принадлежат все объекты---супертип всех типов (включая себя). 3. имя суперкласса всех классов, кроме самого себя. Возможно, я создам новый вопрос в этом направлении. - person charlieb; 29.03.2010
comment
@charlieb: имейте в виду, что классы и типы - это две разные вещи в CL. CL также делит свои объекты на три категории: 1) встроенные классы, такие как числа, символы и строки. 2) структуры и 3) экземпляры CLOS. CLOS позволяет вам писать методы для встроенных типов и структур, но из-за этого они все еще не являются CLOS-объектами. Все объекты CLOS наследуются от STANDARD-OBJECT. Числа, например, имеют класс NUMBER, который сам по себе не является СТАНДАРТНЫМ, а ВСТРОЕННЫМ. - person Rainer Joswig; 29.03.2010
comment
Я думаю, что частью путаницы может быть слово объект. Во многих языках это означает экземпляр класса. В Common Lisp это означает любые данные Lisp -- lispworks.com/documentation/HyperSpec /Body/26_glo_o.htm - person Ken; 31.03.2010
comment
@Кен: Верно. Лисп предшествует ООП. Часто элементы данных Лиспа называются «объектами», потому что их можно отличить от других объектов с помощью функции EQ. В Лиспе, даже в Common Lisp, тогда было много различных объектных систем — например, «Object Lisp» не был основан на классах и где объекты не были экземплярами класса. CLOS был добавлен в CL с опозданием. Существуют даже классы для не-CLOS-объектов, таких как number: (find-class 'number) работает. Имеет смысл говорить об объектах CLOS, когда речь идет о экземплярах классов класса STANDARD-CLASS, а из контекста это неясно. - person Rainer Joswig; 01.04.2010

Для этого вы можете использовать COERCE или FLOAT:

(float 4) => 4.0
(coerce 4 'float) => 4.0
person Xach    schedule 28.03.2010
comment
Привет, Ксах, но могу ли я использовать принуждение, чтобы изменить число на пользовательский класс? - person charlieb; 28.03.2010
comment
Нет. Вы не можете использовать обычные арифметические функции CL для экземпляров ваших собственных классов — они не являются универсальными функциями. - person Xach; 28.03.2010