Documentation: Hints for using the PCL Metaobject Protocol |
The CLOS Metaobject Protocol (MOP) is a semi-standardized reflective extension to CLOS. Most Common Lisp implementations (including CMUCL) implement a metaobject protocol that is similar to the specification given in chapters 5 and 6 of the The Art of the MetaObject Protocol (a book whose title is often abbreviated AMOP). However, the PCL MOP provided by CMUCL has a few differences from AMOP, and behaves differently from the MOP in other Common Lisp implementations in certain respects.
The major issues that can arise are:
(defmethod pcl:validate-superclass ((class meta-foo) (super pcl::standard-class)) t)
PCL, the CLOS implementation that is used in CMUCL, is integrated with the rest of CMUCL in a somewhat incomplete way. The type system of PCL and of the CMUCL kernel have different notions of what a class is. This is because classes are fundamental to the CMUCL type system, yet CMUCL needs to be able to function without PCL loaded (mainly in order to be able to build itself). The way that this problem is resolved is by having the CMUCL kernel maintain parallel class hierarchies. For instance, LISP:CLASS and PCL:CLASS are different types. The function LISP:FIND-CLASS returns instances of LISP:CLASS, whereas the function PCL:FIND-CLASS returns PCL:CLASS instances. For example
USER> (lisp:find-class 'cons) #<built-in-class cons (sealed) {28073C8D}> USER> (pcl:find-class 'cons) #<Built-In-Class cons {2817967D}>
These two classes are in one sense the same class, in that they represent the same type: CONS. However, PCL has its own way of representing that type internally.
In order to make this situation livable, PCL has been hacked up to accept LISP:CLASS objects in the common places where people supply classes to PCL operations. You can also explicitly convert between the two kinds of classes, either by using the class name and the appropriate FIND-CLASS, or by:
(kernel:class-pcl-class lisp-class) ==> the PCL class (kernel:layout-class (pcl::class-wrapper pcl-class)) ==> the LISP class
Another problem area is with generic functions that are called by PCL with classes as arguments. These classes will be PCL:CLASSes, so if you try to specialize on e.g. ALLOCATE-INSTANCE using an EQL specializer, then make sure the class in the specializer is a PCL:CLASS.
People who stick to using standard CLOS operations shouldn't ever notice all this smoke and mirrors. People using standard CLOS operations shouldn't have their packages use the PCL package, since the Common-Lisp package exports a consistent set of definitions for standard CLOS operations.
Though the above hacks usually work for simple stuff, they often seem to break down when defining new metaclasses. What you need to do is explictly specify the PCL:: prefix on the class name.