[comp.lang.clos] Compatible metaclasses?

egdorf@zaphod.lanl.gov (Skip Egdorf) (11/14/90)

I have just installed my bran' new Sun Common Lisp 4.0 and have been trying
some of my pcl code on the lucid CLOS. I have come up with an unexpected error.

I have been using metaclasses to add simple functionality to my classes.
I generally use different metaclasses to add functionality as I go deeper
into the tree of defclass's. This does not seem to work in Lucid's CLOS.

A simple example:

;;;
;;; Start example
;;;

(in-package 'user)

(defclass my-metaclass (standard-class)
  ((a-new-slot-for-classes
    :documentation "Some additional functionality for classes."
    :reader new-slot
    :initform 27)))

(defclass my-special-metaclass (my-metaclass)
  ((another-new-slot-for-classes
    :documentation "Even more functionality for classes."
    :reader another-new-slot
    :initform 53)))

(defclass top-dog ()
  ()
  (:metaclass my-metaclass))

(defclass under-dog (top-dog)
  ()
  (:metaclass my-special-metaclass))

;;;
;;; End example
;;;

The above example works in May-Day PCL. The class under-dog has more functionality
than its superclass.
I can say (new-slot (find-class 'top-dog)) and get 27.
I can say (new-slot (find-class 'under-dog)) and get 27.
I can say (another-new-slot (find-class 'under-dog)) and get 53.

In my new Sun Common Lisp (4.0.1 on SPARC) with Lucid's CLOS, the defclass for
under-dog causes an error

  >>Error: Class UNDER-DOG cannot have class TOP-DOG as a superclass,
    because the metaclasses are not compatible
                                    ^^^^^^^^^^ note the word

(a newline inserted in the error message for readablilty...)

The metaobject protocol draft document contradicts itself (a little)
regarding the validity of this. On pages 3-18 and 3-19 of
Draft 11 from arisia.xerox.com, there is an example of a class
plane with the default metaclass (standard-class) followed by a subclass
sst with a metaclass faster-class.

On page 3-24, mention is made that a class's metaclass is
compatible (note the word, this is the only place that I could find
it in the MOP draft) with its superclass's metaclass. This is done
with validate-superclass.

The description of validate-superclass says that this compatibility
happens in any of three situations:

1. Superclass is T

2. The metaclasses of the class and its superclass are eq

3. The two metaclasses are funcallable-standard-class and standard-class
   and the superclass has no slots.

My example above and the example of planes and sst in the book are
reasonable examples of wanting to add additional functionality to
only some classes in a system. Items 1 and 2 above seem to imply that
the metaclass of ALL classes in a system (derived from one root
superclass, anyway) must be of the same metaclass.

From the point of view of the MOP draft document's specifications
(ignoring the example on 3-18 and 3-19) Lucid's 4.0 seems to be
working correctly (without validate-superclass, but Lucid doesn't
claim to have the entire MOP) and PCL is wrong.

However, I don't understand WHY this restriction is in place. It seems
reasonable to me to have a root superclass (e.g. all-my-objects) with
some simple functionality added to only SOME of its subclasses via
new metaclasses.


I REALLY wanted to have this be a bug in Lucid's 4.0 rather than in
either the MOP or my understanding. It appears that the bug is in
one of the last two. Given that, I would appreciate someone in the
know giving a description of the arguments for the restriction that
all classes in a tree must be of the same metaclass. Or perhaps I am
not understanding something else. Elucidation will be welcome.

					Skip Egdorf
					hwe@lanl.gov

anderson@sapir.cog.jhu.edu (Stephen R. Anderson) (11/14/90)

As it happens, I have copies of two other lisps that include CLOS
running on my Sun 4/110 at the moment, that I'm trying to choose
between. So I tried this little example out on each, and can provide a
couple of data points (even if no clarification). First, Harlequin's
LispWorks (2.06) behaves the same way as Lucid (though with a slightly
less informative error message: "Error: #<STANDARD-CLASS
STANDARD-OBJECT 92c3f4> is an invalid superclass of #<MY -METACLASS
TOP-DOG 79fc04>" where Lucid says "Error: Attempt to define a class
#<My-Special-Metaclass UNDER-DOG> with a super-class of #<My-Metaclass
TOP-DOG>; but their respective metaclasses #<Standard-Class
MY-SPECIAL-METACLASS> and #<Standard-Class MY-METACLASS> are
incompatible").  Franz' Allegro Common Lisp 4.0beta, in contrast,
accepts this situation and behaves as Skip wants it to, allowing me to
read new-slot of top-dog and under-dog and another-new-slot of
under-dog.  So which behavior ought I to prefer?

Steve Anderson

Dept. of Cognitive Science
The Johns Hopkins University