Sonya Keene worked with an early version of CLOS, that had been slightly modified in the final ANSI version, but 99.99999% of the book still works today.
In ANSI Common Lisp
DESCRIBE is a normal function like the functions defined by
DEFUN, that can have no methods. That's why you get an error when you try to define a method for DESCRIBE. But DESCRIBE internally calls the
DESCRIBE-OBJECT generic function, that also takes an additional STREAM argument, what is the output stream to write to.
All you need to do is to replace DESCRIBE with DESCRIBE-OBJECT like this:
Code: Select all
(defclass my-class ()
((a :initarg :a :accessor my-class-a)
(b :initarg :b :accessor my-class-b)
(c :initarg :c :accessor my-class-c)))
(defmethod describe-object ((obj my-class) stream)
(format stream "The object ~s is an instance of class MY-CLASS.~%" obj)
(format stream " The object has three slots:~%")
(format stream " Slot A has a value of: ~a~%" (my-class-a obj))
(format stream " Slot B has a value of: ~a~%" (my-class-b obj))
(format stream " Slot C has a value of: ~a~%" (my-class-c obj))
(values)) ; no return value
There are ways how to write this in one single FORMAT call instead of five but I didn't want to make it too complicated.
The following examples are printed by SBCL, the internal #<MY-CLASS {10061BF423}> representation may look different with CLISP.
Now you get:
Code: Select all
CL-USER> (describe (make-instance 'my-class :a 1 :b 2 :c 3))
The object #<MY-CLASS {10061BF423}> is an instance of class MY-CLASS.
The object has three slots:
Slot A has a value of: 1
Slot B has a value of: 2
Slot C has a value of: 3
; No value
There is also a
PRINT-OBJECT generic function that works exactly like
DESCRIBE-OBJECT, and defines how objects are printed:
Code: Select all
(defmethod print-object ((obj my-class) stream)
(format stream "#<MY-CLASS a: ~a b: ~a c: ~a>"
(my-class-a obj)
(my-class-b obj)
(my-class-c obj)))
Before:
Code: Select all
CL-USER> (make-instance 'my-class :a 1 :b 2 :c 3)
#<MY-CLASS {1006F2F9F3}>
After:
Code: Select all
CL-USER> (make-instance 'my-class :a 1 :b 2 :c 3)
#<MY-CLASS a: 1 b: 2 c: 3>
The
PRINT-OBJECT generic function is also explained in the Keene book.
What I wanted to show is that in ANSI Common Lisp
DESCRIBE and
DESCRIBE-OBJECT work exactly like
PRINT and
PRINT-OBJECT. I think this is one of the reasons why the behaviour of DESCRIBE in ANSI Common Lisp was changed from the old syntax in the Keene book.
- edgar