Overriding describe

Discussion of Common Lisp
Post Reply
J.Owlsteam
Posts: 21
Joined: Wed Jul 29, 2015 7:25 am

Overriding describe

Post by J.Owlsteam » Thu Aug 20, 2015 6:16 pm

Good evening every one, as promised I'm here again :D
I'm having little troubles in trying to override the definition of the describe generic function... reading Sonja's book it seems she can do it without any problems so maybe I'm doing something wrong... I've tried the same way on different implementations and always get the same error, simply typing:

Code: Select all

(defclass my-class () ())
(defmethod describe ((obj my-class)))
I fall in the debugger mode with the error:
CLISP: Describe does not name a generic function
Clozure: The function DESCRIBE is defined as something other than a generic function
SBCL: Describe already names an ordinary function or a macro
It actually seems that describe isn't a generic function and that its value is bounded someway... nevertheless Sonja suggests as good practice its redefinition. How to handle it?
As ever, thanks and greetings :)

Goheeca
Posts: 271
Joined: Thu May 10, 2012 12:54 pm
Contact:

Re: Overriding describe

Post by Goheeca » Fri Aug 21, 2015 1:09 am

You are looking for describe-object.
cl-2dsyntax is my attempt to create a Python-like reader. My mirror of CLHS (and the dark themed version). Temporary mirrors of aferomentioned: CLHS and a dark version.

J.Owlsteam
Posts: 21
Joined: Wed Jul 29, 2015 7:25 am

Re: Overriding describe

Post by J.Owlsteam » Fri Aug 21, 2015 10:14 am

Oh, perfect thank you! :)
Just for completeness... do you know why wasn't I allowed to override directly describe? What sort of function is it?

edgar-rft
Posts: 226
Joined: Fri Aug 06, 2010 6:34 am
Location: Germany

Re: Overriding describe

Post by edgar-rft » Fri Aug 21, 2015 11:21 am

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
Last edited by edgar-rft on Sun Aug 23, 2015 12:28 pm, edited 1 time in total.

J.Owlsteam
Posts: 21
Joined: Wed Jul 29, 2015 7:25 am

Re: Overriding describe

Post by J.Owlsteam » Sun Aug 23, 2015 5:05 am

Perfect perfect... I got it! And I like this simmetry... thanks you ;)

Post Reply