From: Leslie P. Polzer
Subject: Multiple metaclasses
Date: 
Message-ID: <a965f9ab-90b5-4716-88ef-2842a012915b@i12g2000prf.googlegroups.com>
Hello folks,

how do I attach several metaclasses to a class?
I have tried to make a new class combining the metaclasses like that:

(defclass persistent-widget (elephant:persistent-metaclass
weblocks:widget-class)
  ())

(defclass player (...)
(...) (:metaclass persistent-widget))

but SBCL throws the runtime error:

debugger invoked on a SB-PCL::METAOBJECT-INITIALIZATION-VIOLATION in
thread #<THREAD "initial thread" {A6F6799}>:
  Cannot CHANGE-CLASS objects into CLASS metaobjects.
See also:
  AMOP, Initialization of Class Metaobjects

Of course I tried to get wise by reading that section, but haven't
gained anything by that.

How would you specify several metaclasses?

  Leslie

From: Pascal Costanza
Subject: Re: Multiple metaclasses
Date: 
Message-ID: <5rdbggF13r0v1U1@mid.individual.net>
Leslie P. Polzer wrote:
> Hello folks,
> 
> how do I attach several metaclasses to a class?
> I have tried to make a new class combining the metaclasses like that:
> 
> (defclass persistent-widget (elephant:persistent-metaclass
> weblocks:widget-class)
>   ())
> 
> (defclass player (...)
> (...) (:metaclass persistent-widget))
> 
> but SBCL throws the runtime error:
> 
> debugger invoked on a SB-PCL::METAOBJECT-INITIALIZATION-VIOLATION in
> thread #<THREAD "initial thread" {A6F6799}>:
>   Cannot CHANGE-CLASS objects into CLASS metaobjects.
> See also:
>   AMOP, Initialization of Class Metaobjects
> 
> Of course I tried to get wise by reading that section, but haven't
> gained anything by that.
> 
> How would you specify several metaclasses?

I am doing this in several places in ContextL, and I don't get such an 
error in SBCL (nor in the many other CL implementations that I support).

My guess is that you haven't shown us the complete code and that the 
error is somewhere else.

Have you defined appropriate methods on validate-superclass? (Probably 
not related to your error either, but just to make sure...)


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Leslie P. Polzer
Subject: Re: Multiple metaclasses
Date: 
Message-ID: <0897b34a-37d4-4e96-987e-c80787d301a0@f3g2000hsg.googlegroups.com>
> I am doing this in several places in ContextL, and I don't get such an
> error in SBCL (nor in the many other CL implementations that I support).
>
> My guess is that you haven't shown us the complete code and that the
> error is somewhere else.

Okay, here's some more:

(defclass persistent-widget (elephant:persistent-metaclass
weblocks:widget-class)
  ())

(defclass player (widget) (
   (id :reader id :type (integer))
   (nickname :accessor nickname :initarg :nickname)
   (password :accessor password :initarg :password)
   (email :reader email :type (string) :initarg :email)
   ;;; bunch of more slots, all in this fashion. nothing fancy.
) (:metaclass persistent-widget))


(defmethod render-widget-body ((obj player) &rest args)
  (declare (ignore args))
  (render-data obj))

After that I create an instance of 'player':

(defparameter leslie (make-instance 'player))


> Have you defined appropriate methods on validate-superclass? (Probably
> not related to your error either, but just to make sure...)

No. Do I need to? All of MOP that I use is above. I just want to
define
a class that is both a member of Weblocks' 'widget-class' metaclass
and of Elephant's 'persistent-metaclass' metaclass.

My guess is that either I have obmitted something important or one of
those
two packages is at fault.

  Leslie
From: Pascal Costanza
Subject: Re: Multiple metaclasses
Date: 
Message-ID: <5rdfcsF13nle6U1@mid.individual.net>
Leslie P. Polzer wrote:
>> I am doing this in several places in ContextL, and I don't get such an
>> error in SBCL (nor in the many other CL implementations that I support).
>>
>> My guess is that you haven't shown us the complete code and that the
>> error is somewhere else.
> 
> Okay, here's some more:
> 
> (defclass persistent-widget (elephant:persistent-metaclass
> weblocks:widget-class)
>   ())
> 
> (defclass player (widget) (
>    (id :reader id :type (integer))
>    (nickname :accessor nickname :initarg :nickname)
>    (password :accessor password :initarg :password)
>    (email :reader email :type (string) :initarg :email)
>    ;;; bunch of more slots, all in this fashion. nothing fancy.
> ) (:metaclass persistent-widget))
> 
> 
> (defmethod render-widget-body ((obj player) &rest args)
>   (declare (ignore args))
>   (render-data obj))
> 
> After that I create an instance of 'player':
> 
> (defparameter leslie (make-instance 'player))
> 
> 
>> Have you defined appropriate methods on validate-superclass? (Probably
>> not related to your error either, but just to make sure...)
> 
> No. Do I need to? All of MOP that I use is above. I just want to
> define a class that is both a member of Weblocks' 'widget-class' metaclass
> and of Elephant's 'persistent-metaclass' metaclass.

Oh, yes, you should. ;)

> My guess is that either I have obmitted something important or one of
> those two packages is at fault.

It's worse than that: Different metaclasses are in general not 
compatible, especially when they stem from different libraries developed 
by different vendors. It is quite likely that each metaclass is 
'correct' when considered in isolation, but when composed in the way 
that you do it, suddenly doesn't work anymore, because the different 
metaclasses interfere in the way they modify the semantics of classes.

In order to convince yourself that persistent-metaclass and widget-class 
work in conjunction, you should either study the documentation of the 
respective metaclasses to see what they state in terms of metaclass 
compatibility, or (more likely) study the respective source code to see 
what they do and whether they can be composed by fixing some erroneous 
interactions in methods of your own persistent-widget metaclass.

This is all not trivial. Maybe it's easier to just create sibling 
classes, each of which is an instance of the respective metaclass, and 
just compose them by letting their instances refer to each other. (But 
this is just a guess, I don't know the details of those two libraries.)


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/