in reply to Perl 6 Shocking Revelations II - classes are built, not declared
I think calling this a "shocking revelation" is maybe a bit overkill, despite what you say in your linked PDF, this is not all that odd, in fact, as with most language features, LISP/CLOS had this like 20 years ago and Smalltalk has being doing this for maybe 28 or so years (Smalltalk-80). In fact, just about any heavily meta-circular-leaning OO language will do this to some degree or another.
It looks like you have not taken a look at Moose, Class::MOP and perhaps the older Perl6::MetaModel work in Pugs or the newer MO work either? We determined back then that classes can easily be desugared into a series of metaclass calls, and if you take a look at Moose, that is *exactly* how it works. We also figured our a number of these details already, some more documented then others of course, but it is all there and myself and the authors of the other bits would surely be happy to discuss/explain/etc if you want.
So, anyway, here are my comments on your paper:
And those things that look like declarations are actually function calls on the “class builder”
I understand that you are probably trying to make this more digestable, but saying "functions" is just wrong, they would be methods. I am also not sure that calling it a "class builder" is better then just jumping in a calling them "metaclasses", especially since you start talking about metaobjects in the very next paragraph. Perl has a long history of "class builders" many of which tended to be horrid kludges full of symbol table manipulation and such, so it is kind of loaded term in the community.
my Metaobject $dogclass = P6opaque_builder.new("Dog");
The type "MetaObject" does not make sense as the type of a metaclass, nor does it makes sense that calling new on "P6opaque_builder" would return an instance of "MetaObject". An instance of a metaclass could be called a metaobject, but so could any other meta-level instance (we refer to the Moose::Meta::Attribute instances as meta-objects all the time). This really should be something more like:
my MetaClass $dog_class = MetaClass.new(name => "Dog", repr => "p9opag +ue");
What functions really are there to be called on the builder is what we need to design, rather than wait for every implementation to come up with something different.
The point is that this is not some deep dark magic, but a well-defined part of Perl 6.
Again s/functions/methods/ and s/builder/metaclass/ please, that is critical.
First, let me say that I agree with this, but last I recall @Larry had declared that the meta level was not part of Perl 6 the language itself, but implementation dependent. One thing we have discovered with Moose, is that if you have an open and meta-circular MOP you can extend pretty much everything you would ever need too, and so on some level new implementations are not needed if the MOP is sufficiently flexible and extendable (why re-write MetaClass, when you can simply subclass it).
The exact same interface should be used for creating roles too.
This is only sort of true, and there be dragon here. Roles require special treatment that classes do not. For instance, in Moose::Role the creation of attributes is deferred, so no accessor creation is actually done in the role, but instead is done when the role is applied to the class. This is important, because a role may applied to many classes and so sharing the same attribute metaobject between several classes makes for some tricky problems. Of course that is somewhat implementation dependent, but I have been futzing with roles and traits for several years now (I wrote Class::Trait 0.01 in March 2004, and have written and re-written about 10-12 role systems over the last 4 years) so I speak from real-world experience on this one.
I think the add_attributes example is pretty confusing actually, the fiddling with ::?CLASS doesn't make a lot of sense to me, I think it needs more clarification. Honestly I would look at it more like this:
Why do grammar gymnastics to get access to the syntactic sugar when you simply use the MOP directly? IMO this code is much cleaner in it's intentions now.sub add_attributes (MetaClass ^class, Int $defval) { ^class.meta.add_attribute( name => "$.a" , type => Int, default => $defval ); ^class.meta.add_attribute( name => "$.c" , type => Str ); } class George { has Int $.d; add_attributes(?CLASS, 5); }
The parser produces an AST representation, and allows Perl code to examine and modify the tree before compilation continues. This is specified for “macro” features, for writing more interesting grammatical constructs, and will be needed as part of the Metaobject interface.
s/MetaObject/MetaClass/
You are heading down a slippery slope there, the meta-object manipulations should be done *after* all macros have been expanded In fact, if you look at CLOS, you will note that the surface class declarations are all just macros, which expand into metaobject method calls.
In Perl 6, it is not clear yet how close the situation is to being exactly the same. Every object has a reference to a “meta object” that controls dispatch, so blessing would refer to installing this meta object reference. But is the meta object the same as a package?
Yes, it is the same (sort of), a Class isa Module and a Module isa Package, take a look at this diagram here, I originally created it for the Perl6::MetaModel, but altered it to help explain the structure of Class::MOP.
The class builder is not the same object as the meta object.
Why not? Is not a class just an instance of a metaclass? You don't need an ObjectBuilder to create instances of regular classes, why need a ClassBuilder to make an instance of a metaclass?
The “meta object” is the object that is in charge of dispatching normal (single) dispatch method calls.
A metaobject should do sooooooo much more than that, what about introspection? If this is all that the metaobject does then HOW is going to return a pretty useless object.
This is not called the meta class because it does not have to be any particular type.
I don't understand this statement, if it responds to a particular interface, is it not the type of that interface?
A systematic way of using meta objects is called the MOP.
Yes, this is a correct definition, but a MOP can be so much more. Do yourself a favor and get a hold of a copy of "The Art of the Metaobject Protocol" by Gregor Kiczales, it will open your eyes to the possibilities of MOPs.
The meta object needs to be called using a more primitive system than method dispatch. The more primitive way of organizing multiple functions into a unit is with a package containing subs and data.
Not in a meta-circular system it doesn't. Consider the this code, it creates a fully bootstrapped object system a single method of dispatch, no need to seperate them. The Perl6::MetaModel itself actually did something like this (my p6 is rusty, so forgive the syntax errors):
The only thing that this assumes is that you have defined the message send operator (.) and that it can find the "dispatch_method" method in the objects metaclass. I think S12 defines the WALKCLASS and WALKMETH macros to do that.my ^Class; ^Class = create_low_level_instance( class => ^Class, # the instance has a ref to the metaobject methods => {}, # some place to store the method refs # ... now create the other # fields in the class object ); sub _add_method_bootstrapper ($class, $method_name, $method) { low_level_instance_access($class, 'methods'){$method_name} = $meth +od; } # first install the method dispatcher _add_method_bootstrapper( ^Class, 'dispatch_method', -> $obj, $method_name, @args { # ... find the method, either in the # the local class, or in an inherited # class. Then call the method ref with # the args. } ); # now add the add_method method ... _add_method_bootstrapper( ^Class, 'add_method', &_add_method_bootstrapper, ); # whalla, you now have bootstrapped method dispatch ^Class.add_method('get_method' => -> $method_name { low_level_instance_access($class, 'methods'){$method_name} }); # go about building the rest of Class here
Study the MO system in Pugs, it has a lot of ways to do optimized method dispatch. The SMOP project was also using it as a model for it's internal method dispatch IIRC too. Most, if not all, of your questions are already answered by that.
The name Metaobject exists as a role.
This is the direction which Moose 2.0 will be taking too, you should read this paper Uniform and Safe Metaclass Composition, it describes how that did this exact thing in in Smalltalk with Traits.
The name MetaMetaobject exists as a Package.
Ouch, avoid the MetaMeta stuff, it is a sure sign of a bad meta design. If you need proof, take a look at Smalltalk 72, or simply answer me the question, what is the type of the metaobject of a MetaMetaObject? Turtles all the way down is better done with a meta-circular system, i will refer you again to the Class::MOP image and see the little cycle at the top of the Class? That is what make Class an instance of Class and ties the knot so that you can have infinite turtles without having to make a MetaMetaMetaMetaMetaMetaMetaMetaObject.
$?CLASS_BUILDER and $+CLASS_BUILDER.
If you go with a metacircular system you wont need this, cause $?CLASS will be sufficient.
Okay, thats about all I got for now, I should have been doing $work a long time ago actually. Hope this helps.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Perl 6 Shocking Revelations II - classes are built, not declared
by John M. Dlugosz (Monsignor) on May 08, 2008 at 23:49 UTC | |
by stvn (Monsignor) on May 09, 2008 at 03:32 UTC | |
by John M. Dlugosz (Monsignor) on May 09, 2008 at 13:47 UTC | |
|
Re^2: Perl 6 Shocking Revelations II - classes are built, not declared
by John M. Dlugosz (Monsignor) on May 08, 2008 at 23:41 UTC | |
by stvn (Monsignor) on May 09, 2008 at 03:36 UTC | |
by John M. Dlugosz (Monsignor) on May 09, 2008 at 13:53 UTC |