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:
- Make sure that you use symbols from the right package. A number
          of symbols, such as STANDARD-CLASSexist both in theCOMMON-LISPpackage and in thePCLpackage. For MOP programming you should be using the symbols from the PCL package.
- CMUCL has a package named MOP, which exports most (but not all) of the symbols defined in AMOP.
- Since CMUCL uses special wrappers around class-objects, you
          sometimes need to use PCL::COERCE-TO-PCL-CLASSto coerce the wrapper objects into real MOP-aware objects. For example, this occurs when using theCLASS-OFfunction.
- You may need to define methods on PCL:VALIDATE-SUPERCLASSmore often than is said in AMOP. For example, consider a class calledFOOwhose metaclass isMETA-FOO. Class FOO inherits from class T, whose metaclass isSTANDARD-CLASS, and in the PCL MOP you have to declare that this combination of metaclasses is valid:(defmethod pcl:validate-superclass ((class meta-foo) (super pcl::standard-class)) t)
Details on the class schizophrenia
          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.