Advertisement
Guest User

Untitled

a guest
Mar 22nd, 2019
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lisp 2.74 KB | None | 0 0
  1. (defmacro define-tuple (class-name parents slots &optional documentation)
  2.   "This is just to save my hands, since Netfarm class slots are mostly disjoint
  3. and have the same printer basically.
  4. CLASS-NAME is the name of the slot, PARENTS should be called
  5. DIRECT-SUPERCLASSES to be accurate, SLOTS are a modified slot description list,
  6. and DOCUMENTATION is the docstring.
  7.  
  8. SLOTS takes the form (name . plist), where plist contains:
  9. - :READER, the reader/setter of the slot,
  10. - :READ-ONLY, truthy if the slot should be read-only,
  11. - :INITARG, the keyword argument,
  12. - :INITFORM, the default value.
  13.  
  14. This generates the DEFCLASS form, and a method on PRINT-OBJECT."
  15.   (let ((not-found (gensym "NOT-FOUND"))
  16.         (slot-alist nil))
  17.     (flet ((getf-or-default (list value &optional default)
  18.              (let ((value (getf list value not-found)))
  19.                (if (eql value not-found)
  20.                    default
  21.                    value))))
  22.       `(progn
  23.          (defclass ,class-name ,parents
  24.            ,(loop
  25.                for (name . arguments) in slots
  26.                for reader-name = (or (getf arguments :reader)
  27.                                      (intern (format nil "~a-~a" class-name name)))
  28.                do (push (cons name reader-name) slot-alist)
  29.                collect `(,name :initarg  ,(getf-or-default arguments :initarg
  30.                                                            (intern (symbol-name name) 'keyword))
  31.                                :initform ,(getf-or-default arguments :initform
  32.                                                            `(error
  33.                                                              ,(format nil "~a is required" name)))
  34.                                ,(if (getf arguments :read-only)
  35.                                     :reader :accessor)
  36.                                ,reader-name))
  37.            ,@(unless (null documentation)
  38.                (list (list :documentation documentation))))
  39.          (defmethod print-object ((object ,class-name) stream)
  40.            (print-unreadable-object (object stream :type t :identity t)
  41.              (pprint-logical-block (stream nil)
  42.              ,@(loop for ((name . reader) . continuep) on (reverse slot-alist)
  43.                      collect `(progn
  44.                                 (write-char #\: stream)
  45.                                 (write-string ,(symbol-name name) stream)
  46.                                 (write-char #\Space stream)
  47.                                 (pprint-newline :miser stream)
  48.                                 (prin1 (,reader object) stream)
  49.                                 ,@(when continuep
  50.                                     '((write-char #\Space stream)
  51.                                       (pprint-newline :linear stream))))))))))))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement