The Meta-Object Protocol

The MOP (from *The Art of the Metaobject Protocol*, Kiczales et al.) exposes CLOS's own implementation as CLOS objects, so you can customize how classes, slots, and generic functions behave. It isn't part of the ANSI standard, but every major implementation supports it; use the closer-mop library for portability.

MOP applications: ORMs that map slots to columns (Mito), persistent objects, validation, automatic serialization, proxies, and memoized/traced generic functions (funcallable-standard-class).

(ql:quickload "closer-mop")

;; Introspection
(closer-mop:ensure-finalized (find-class 'dog))
(mapcar #'closer-mop:slot-definition-name
        (closer-mop:class-slots (find-class 'dog)))       ; (NAME SOUND BREED)
(closer-mop:class-direct-superclasses (find-class 'dog))  ; (#<STANDARD-CLASS ANIMAL>)
(closer-mop:generic-function-methods #'speak)

;; Generic object-to-plist serializer using introspection
(defun object->plist (obj)
  (loop for slot in (closer-mop:class-slots (class-of obj))
        for name = (closer-mop:slot-definition-name slot)
        when (slot-boundp obj name)
          append (list (intern (symbol-name name) :keyword) (slot-value obj name))))
(object->plist (make-instance 'dog :name "Rex"))         ; (:NAME "Rex" :SOUND "Woof" :BREED "mixed")

;; Custom metaclass: count instances automatically
(defclass counted-class (standard-class)
  ((instance-count :initform 0 :accessor instance-count)))
(defmethod closer-mop:validate-superclass ((c counted-class) (s standard-class)) t)
(defmethod make-instance :after ((class counted-class) &key)
  (incf (instance-count class)))

(defclass widget () () (:metaclass counted-class))
(make-instance 'widget) (make-instance 'wid
…