lisp-maintainers / defclass-std

A shortcut macro to write DEFCLASS forms quickly
9 stars 0 forks source link

print-object/std (with snippet) #2

Open vindarel opened 2 months ago

vindarel commented 2 months ago
(defclass-std:defclass/std foo2 ()
  ((bar baz)))

(defparameter foo2 (make-instance 'foo2))

=> #<FOO2 {1006584EC3}>

(print-object/std foo2)

=> #<FOO2 (BAR NIL), (BAZ NIL) {1006584EC3}>

(defun collect-object-slots (obj)
  (loop for slot in (sb-mop:class-direct-slots (class-of obj))  ;; <-- or only class-slots, for inherited slots too
                  for name = (sb-mop:slot-definition-name slot)
                  for val = (if (slot-boundp obj name)
                                (slot-value obj name)
                                "UNBOUND")
                  collect (list name val)))

(defmacro print-object/std (class)
  `(defmethod print-object ((obj ,class) stream)
     (print-unreadable-object (obj stream :type t :identity t)
       (format stream "~{~a~^, ~}"
               (collect-object-slots obj)))))
vindarel commented 2 months ago

there's something already:

   There's a shortcut to setup a basic printing behaviour of a class, using `printing-unreadably`:
```lisp
(printing-unreadably (field2 field3) (class/std myclass field1 field2 field3))

; which expands to:

(PROGN
  (CLASS/STD MYCLASS FIELD1 FIELD2 FIELD3)
  (DEFMETHOD PRINT-OBJECT ((MYCLASS MYCLASS) #:STREAM1722)
    (PRINT-UNREADABLE-OBJECT (MYCLASS #:STREAM1722 :TYPE T :IDENTITY T)
      (FORMAT #:STREAM1722 "FIELD2: ~s, FIELD3: ~s"
              (FIELD2 MYCLASS) (FIELD3 MYCLASS)))))

but

(defclass-std:printing-unreadably (field1 field2 field3) (defclass-std:class/std myclass field1 field2 field3))

(make-instance 'myclass :field1 "one")
;; => #<MYCLASS FIELD1: "one", FIELD2: NIL, FIELD3: NIL {1008944E63}>
vindarel commented 2 months ago

done: print-object/std prints all slots.