views:

38

answers:

2

I have written a polynomial class along the lines described in SICP 2.5.3 (except using defclass). I would like to be able to seamlessly add and multiply polynomials and regular numbers but I can't make change-class accept a number.

I tried to simplify the problem by changing class from an integer to a float:

(change-class 4 'float)

but that gave me the error:

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]

I get an error of the same form from (fyi):

(change-class 4 'polynomial)

I'm going to go ahead and implement a manual conversion but I would prefer to use the built-in clos facilities.

As Xach points out I could use coerce or float to change 4 to a float. That was intended as a simpler example of what I was trying to do and to remove any possibility of my update-instance-for-different-class being wrong.

Here is the longer version of what I tried that didn't work:

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

I still get an error like the example above:

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  A: 

You can use COERCE or FLOAT to do that:

(float 4) => 4.0
(coerce 4 'float) => 4.0
Xach
Hey Xach, but can I use coerce to change the number to a custom class?
charlieb
No. You can't use normal CL arithmetic functions on instances of your own classes -- they're not generic functions.
Xach
+1  A: 

You can't use CHANGE-CLASS with numbers. Numbers are not instances of CLOS classes. CHANGE-CLASS is also thought to destructively modify an instance to a new class, without changing the identity of the original instance.

I would either:

  • add methods to CHANGE-CLASS that does what you want

  • or write a function CHANGE, that implements various custom coercion rules and calls CHANGE-CLASS for any change from one CLOS class to another CLOS class.

Rainer Joswig
Thanks, it seems I am confused because I recall that cl is objects all the way down but perhaps it is not CLOS all the way down.I just checked the hyperspec and it says that about t that "2. the name of the type to which all objects belong---the supertype of all types (including itself). 3. the name of the superclass of all classes except itself. "Perhaps I will create a new question along these lines.
charlieb
@charlieb : keep in mind that classes and types are two different things in CL. CL also divides it objects into three categories: 1) built-in classes like numbers, characters and strings. 2) structures and 3) CLOS instances. CLOS allows you to write methods for built-in types and structures, but these are still not CLOS objects because of that. CLOS objects all inherit from STANDARD-OBJECT. Numbers for example have a class NUMBER, which itself is not a STANDARD-CLASS, but a BUILT-IN-CLASS.
Rainer Joswig
I think part of the confusion might be the word "object". In many languages, it means "an instance of a class". In Common Lisp, it means "any Lisp datum" -- http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_o.htm
Ken
@Ken : Right. Lisp predates OOP. Often Lisp data items are called 'objects', because they can be distinguished from other objects using the EQ function. Lisp, even Common Lisp, then had many different object-systems - for example 'Object Lisp' was one that was not class-based and where objects were not instances of a class. CLOS has been added late to CL. There are even classes for non-CLOS objects like number: (find-class 'number) works. It makes sense to speak of 'CLOS objects" when one means especially instances of classes of class STANDARD-CLASS and the context does not make that clear.
Rainer Joswig