Re: Custom Metaclass and Inheritance of Class Methods

2005-10-14 Thread Rob Kinyon
> == CONCLUSION / WRAP-UP
>
> So, now that I have sufficiently bored you all to tears, I will do a
> quick re-cap of the main question, and the possible solutions.
>
> Should metaclasses be "inherited" along normal class lines?
>
> Meaning that if Foo uses a custom metaclass, and Bar isa Foo, then
> Bar also uses that metaclass.
>
> If we say yes, then I think it is clear that in order to get a sane
> method and predictable resolution order the custom metaclass would
> always need to precede the inherited eigenclass in the superclass
> list. (see the last example above).
>
> If we say no, then we need to introduce another anyonomous class into
> our mix, which we call an 'x' class. The 'x' class would need to use
> a breath-first dispatch order in order to produce a sane and
> predictable method resolution order.

I would like to expand on my position in the discussion Steve and I
had, which is the "no" position. The crux of my view is that Foo is an
instance of some custom metaclass. Bar is an instance of Class (for
the sake of argument). Foo and Bar are unrelated, save for the fact
that instances created by Bar's new() function will have access to all
the behaviors and state that instances created by Foo's new() function
will have.

This is why I also feel that class methods shouldn't have the same MRO
as instance methods, but that's a moot discussion.

Rob


Custom Metaclass and Inheritance of Class Methods

2005-10-13 Thread Stevan Little

Hey All,

So, given the abundance of positive responses ;) for my "class  
methods don't inherit" proposal, I have decided to withdraw that  
proposal (see my last response on the thread). Of course, this means  
we now have to work out the details of exactly *how* they get  
inherited in all situations. The trickiest one being in the presence  
of custom metaclasses. So, onto the questions.


(NOTE: if you get bored about half-way through this mail (and you  
probably will), there is a conculsion/wrap-up at the very bottom that  
you can probably safely skip ahead too)


Should custom metaclasses are "inherited" along "normal" subclass lines?

This would mean that if Foo uses CustomMeta as it's metaclass, any  
subclass of Foo will do the same. This is something Larry mentioned,  
and something I had been thinking about a lot myself and discussed  
recently with Rob Kinyon. I drew a diagram in my response to Larry  
that looked like this:


  Class
^
:
CustomMeta
^
:
  eFoo<...eBar
^  ^
|  |
   Foo<...Bar

This shows the structure which would be created. The result is that  
method dispatch would go like this:


Bar.foo
  eBar.get_method(foo)
eFoo.get_method(foo)
  CustomMeta.get_method(foo)
Class.get_method(foo)
  ! No Method Found Error !

I think this makes sense in many ways since CustomMeta can  
theoretically add capabilities to the Foo class, which one would want  
inherited by subclasses of Foo. (NOTE: if CustomMeta adds instance  
methods to Foo, they will get inherited, mostly I am talking about  
class functionality here)


However, I can also see where it would make sense for this *not* to  
behave this way. But if we the opposite approach, the eigenclass/ 
metaclass hierarchy begins to get more complex.


To start with, we would need to create another anon-class (called  
xFoo here) which uses multiple inheritence to inherit from eFoo and  
CustomMeta, then eBar would inherit from eFoo (and through eFoo, to  
Class), this would keep CustomMeta out of Bar's method dispatch path.


  Class
^^...
:   :
CustomMeta  :
^   :
:   :
  xFoo...>eFoo<...eBar
^   ^
|   |
   FooeFoo   xBar>eBar
^   ^ ^:
|   :.|:
| |
   Foo<..Bar

The method dispatch path for this is pretty much the same as above,  
with the addition of CustomMeta2. This example now actually brings up  
another issue.


What should the superclass ordering be within the x* classes?

If eBar comes first, followed by CustomMeta2, then we get the  
following method dispatch path:


Bar.foo
  xBar.has_method(foo) # xBar should never have any of it's own method
eBar.has_method(foo)
  eFoo.has_method(foo)
CustomMeta2.has_method(foo) # this would fall here under C3
  Class.has_method(foo)
! Method Not Found Error !

But if CustomMeta2 comes first, followed by eBar, then we get the  
following method dispatch path:


Bar.foo
  xBar.has_method(foo)
CustomMeta2.has_method(foo)
  eBar.has_method(foo)
eFoo.has_method(foo)
Class.has_method(foo)
  ! Method Not Found Error !

The question really is, which has precedence, the custom metaclass,  
or the local class methods (including class methods inherited along  
"normal" class lines)?


Now, all these method dispatch paths are using the C3 MRO. And  
personally I find neither of these approaches to be the best. One  
alternate (but kind of whacky) approach would be to not use C3 here,  
but instead use breath-first traversal.


Now, this may seem really odd at first, but given the highly regular  
structure of these class groupings, it might make the most sense.  
Here is what that method dispatch path might look like:


Bar.foo
  xBar.has_method(foo)
eBar.has_method(foo)
  CustomMeta2.has_method(foo)
eFoo.has_method(foo)
  Class.has_method(foo)
! Method Not Found Error !

Notice how the eBar (which hold's Bar's class methods) is first,  
followed by the CustomMeta2 class, the followed by eFoo, then onto  
Class.


This specialized dispatching beha