Method Dispatch with Eigenclasses

Stevan on 2005-10-09T02:45:21

This past week I have been busy with $work, however, I have been thinking quite heavily about how Eigenclasses can fit into the Perl6-MetaModel. Currently the implementation has limited support (actually it's pretty much broken support) for eigenclasses, and the past 3-4 attempts I have made to clean things up have resulted in a lot of svk revert commands. So finally I decided to sit down and draw things out.

The first diagram I made was your basic vanilla method dispatch. It shows both instance method dispatch as well as class method dispatch. This diagram illustrates the key issue with class methods, in that they do not fit cleanly into a meta-model. This can also be seen when you look at the method signature of a class method: class Bar { method foo (Class $c:) { ... } } In any other method, the invocant (shown as $c here) would be of the same type as the class in which it is defined. But here the signature of the class method shows that the invocant should be of type Class, however that is not where the method is defined.


This issue is even more apparent in CLOS, where methods are represented with generic functions (which are a lot like multi-methods). In CLOS the first parameter of a method has what is called a specializer (which is basically the "type" of that expected parameter) that parameter is used by the CLOS system to associate a method with a particular class. Here is a short example of a generic function foo which is associated with the class Bar. (defgeneric foo (self)) (defmethod foo ((Bar self) ( ... )) The first line defines the generic function foo with the single parameter self. The second line defines a method of that generic function, specialized for the Bar class. Now when we create a class-method called baz, it will look like this: (defmethod baz ((standard-class c)) (...)) By making the type of our parameter standard-class CLOS will associate this method with all instances of standard-class, which is every class in the system.


So you can see, it is impossible to specialize a class method to one particular class using these meta-models.

Eigenclasses to the rescue!!

My second diagram shows how class-methods can be implemented using ruby-style eigenclasses (or singleton-methods as they are also called). The eigenclass hierarchy (show here with the e- prefix) essentially mirrors the normal class hierarchy, but instead of storing instance methods, they store class methods. (This parallel hierarchy actually reminds me of the Smalltalk metaclass hierarchy in some ways, which is why I think it "smells" right to me).

Using the eigenclasses results in a very normalized method dispatch mechanism where instance method and class method dispatch are exactly the same. What else can I say about that but ruby++.

The only point at which things get messy is when we introduce an intentional subclass of Class. Like this: class Baz is Class { ... } class Foo meta Baz { ... } class Bar is Foo { ... } The result is that e-Foo inherits from Baz, and since e-Bar inherits from e-Foo, e-Bar gets methods from Baz, which is probably now what was intended. I didn't even bother to draw this out since it gets really really messy. However, it occurred to me that using Role composition to inject class methods, it might be possible to accomplish most anything you would want to accomplish through subclassing Class anyway. However, this needs more contemplation, and so I will save it for another day.


- Stevan