From: Tamas Papp
Subject: standard print-object method for classes
Date: 
Message-ID: <87zm25kcwx.fsf@pu100877.student.princeton.edu>
When I define a class -- for example

(defclass foo () ((a :initform 0) (b :initform 1)))

it is printed opaquely, eg

CL> (make-instance 'foo)
#<FOO {B0F3321}>

I have learned how to write print-object methods for my own classes,
but I wonder if there is a "default" method I could use (would be
especially useful when I haven't finalized the class hierarchy and I
am just writing exploratory code).

Thanks,

Tamas
From: David Lichteblau
Subject: Re: standard print-object method for classes
Date: 
Message-ID: <slrnf94ass.6a8.usenet-2006@babayaga.math.fu-berlin.de>
On 2007-07-09, Tamas Papp <······@gmail.com> wrote:
> I have learned how to write print-object methods for my own classes,
> but I wonder if there is a "default" method I could use (would be
> especially useful when I haven't finalized the class hierarchy and I
> am just writing exploratory code).

You could invent a structure-like syntax, and query the class for its
slots using the MOP.

CL-USER> (make-instance 'foo :b (make-instance 'foo :a 5))
#.(MAKE-INSTANCE 'FOO :A 0 :B #.(MAKE-INSTANCE 'FOO :A 5 :B 1))                 


(defclass foo ()
    ;; note added :INITARGs for MAKE-INSTANCE
    ((a :initform 0 :initarg :a)
     (b :initform 1 :initarg :b)))

;;; Method specialized on FOO, but could be used for any other class.
;;; (Change SB-MOP to your implementation's MOP package as appropriate.)
(defmethod print-object ((object foo) stream)
  (if (and *print-pretty* *read-eval*)
      (let* ((class (class-of object))
	     (slots (remove-if-not #'sb-mop:slot-definition-initargs
				   (sb-mop:class-slots class))))
	(pprint-logical-block (stream nil :prefix "#.(" :suffix ")")
	  (format stream "~A '~A" 'make-instance (class-name class))
	  (let ((remaining-slots slots))
	    (when remaining-slots
	      (write-char #\space stream)
	      (pprint-newline :linear stream)
	      (loop
		 (pprint-pop)
		 (let* ((slot (pop remaining-slots))
			(name (sb-mop:slot-definition-name slot))
			(value (slot-value object name))
			(initarg
			 (car (sb-mop:slot-definition-initargs slot))))
		   (write initarg :stream stream)
		   (write-char #\space stream)
		   (pprint-newline :miser stream)
		   (unless (constantp value)
		     (write-char #\' stream))
		   (write value :stream stream)
		   (when (null remaining-slots)
		     (return))
		   (write-char #\space stream)
		   (pprint-newline :linear stream)))))))
      ;; trivial fallback, could be more fancy
      (print-unreadable-object (object stream))))