I came across some strange behaviour when trying to customize the print-object
function of a CLOS object. The function does generate the intended string, but it appears outside the object definition (i.e. <OBJECT-NAME >
followed by the string I wanted after the >
character). The skeleton code below reproduces the issue:
(defclass object () ;;; Define some object...
((element-count
:initarg :element-count
:accessor n)
(first-element
:initform nil
:accessor 1st)
(last-element
:initform nil
:accessor end)))
(defmethod print-object ((obj object) stream) ;;; ...and then its print-object method
(print-unreadable-object (obj stream :type t))
(with-accessors ((first 1st)
(last end)
(n n))
obj
(format stream " ~[empty~:;:elements ~:*~d :content ~:*(~[~;~a~;~a ~a~:;~a ... ~a~])~]"
n first last)))
The output strings appear thus:
(defvar o1 (make-instance 'object :element-count 0)) => #<OBJECT > empty
(defvar o2 (make-instance 'object :element-count 1)) => #<OBJECT > :elements 1 :content (NIL)
(defvar o3 (make-instance 'object :element-count 2)) => #<OBJECT > :elements 2 :content (NIL NIL)
(defvar o4 (make-instance 'object :element-count 10)) => #<OBJECT > :elements 10 :content (NIL ... NIL)
I don't understand this output. Per the docs, printing outside the space shouldn't ever happen. Or should it? Well, over to you! By the way, I'm using SBCL on Portacle in Windows.
You misplaced parens - print-unreadable-object
creates an environment which should encompass the whole print-object
body:
(defclass airplane () ((tail-number :initarg tail :accessor plane-tail)))
(defmethod print-object ((plane airplane) stream)
(print-unreadable-object (plane stream :type t)
(princ (plane-tail plane) stream)))
(make-instance 'airplane 'tail 1234)
==> #<AIRPLANE 1234>