and think through what this means. Imagine defining class members in subroutines that are themselves not part of the class!class Fustian { my $var1; has $.a; if $?OS ~~ /Windows/ { has $.b; say “adding Windows support”; } ...
I'm trying to collect the existing wisdom and then proceed with a design document. Please check out the PDF file or the odt file. I think it's time to nail down some of these details.
—John
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Perl 6 Shocking Revelations II - classes are built, not declared
by moritz (Cardinal) on May 08, 2008 at 13:15 UTC | |
(And arbitrary attributes an be added in p5 objects as well - but I don't have to show an example for that ;-) This may be shocking if your background is primarily a C++ or Java one, but for perl hackers that's old news ;-) Update for the monks who are not so familiar with Perl 6 object orientation: In Perl 6 a class { stuff } directive runs stuff at compile time, "as the body of a method of the metaclass, which is responsible for interpreting the keywords of the class definition." (S12) Why do we need meta classes? Well, perl 5 showed us that it's not very good to stick one object model - many programmer think it's not the best solution, and invent clever stuff like Moose to get around these limitations. In Perl 6 you can just define your own meta classes if you don't like the default object model. That's why a class "declaration" is in fact just code that runs at compile time, and builds a class out of it. | [reply] [d/l] [select] |
by John M. Dlugosz (Monsignor) on May 08, 2008 at 23:32 UTC | |
| [reply] |
|
Re: Perl 6 Shocking Revelations II - classes are built, not declared
by stvn (Monsignor) on May 08, 2008 at 16:04 UTC | |
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: In section 2And 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:
In Section 2.1What 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. 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. In Section 2.2I 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. In Section 4The 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. In Section 4.3The 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? In Section 4.4The “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? In Section 4.5A 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. In Section 5.1The 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. In Section 5.3Study 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. In Section 5.4The 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. In Section 6.2$?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.
-stvn
| [reply] [d/l] [select] |
by John M. Dlugosz (Monsignor) on May 08, 2008 at 23:49 UTC | |
I'm trying to stay away from being locked into a class/metaclass system at all. Metaclasses sounds like Smalltalk, not like Self/Javascript. The meta OBJECT is the HOW, the higher-order-workings, but does not have to represent a "class" per-se. Also, the thing that builds a class (if you have them) by creating the package, internal structures, and creating the meta object does not have to be the same object as that which is installed as the HOW. They could be different interfaces on the same object, but there is no reason they need to be, and some reasons why they don't. Perhaps I need to separate out layers and not worry about classes and class{} syntax at all when describing the primordial SMD system that does not need to even have classes. Make the jump to the traditional class approach, and the "here is support for making those." —John | [reply] |
by stvn (Monsignor) on May 09, 2008 at 03:32 UTC | |
Metaclasses sounds like Smalltalk, not like Self/Javascript. Careful, prototype OO is not all it is cracked up to be, it is enjoying a small comeback now that Javascript is being taken seriously. But having been a Javascript programmer for 10+ years now, I can say, its not as cool as people think it is, it's just different. Prototype OO offers you a finer grained re-use mechanism with the prototypical object, but it fails to scale to the needs of larger project organization. Whereas classes have proven themselves in this regard, and Roles with their horizontal re-use have great potential. The prototype-ish features of Perl 6, specifically the "class but undef" feature: The value of $fido is undef, but it is typed as a Dog, and can therefore respond to $fido.can('bark'), but cannot respond to $fido.bark(). This can easily be implemented by applying a runtime role to the undef value, that role is parameterized with the class (in this case Dog) and can then respond to the limited number of method calls. Also, it is much easier to create a prototype OO system on top of a class based system then it is to do the opposite. Here is an example of Prototype OO layer for Moose, and at one point I had a version of the Perl 6 MetaModel that was in Javascript which would have shown a good example of how tedious is to make classes in prototype land, but you can actually just take a look at all the new JS frameworks there, most of them try to do it.
-stvn
| [reply] [d/l] |
by John M. Dlugosz (Monsignor) on May 09, 2008 at 13:47 UTC | |
by John M. Dlugosz (Monsignor) on May 08, 2008 at 23:41 UTC | |
I still need to essay it to non-Perl people when Perl 6 takes over the world (or to help it do so). —John | [reply] |
by stvn (Monsignor) on May 09, 2008 at 03:36 UTC | |
I was worried that everything discussed on Perl6-language is pretty much lost to verbal lore, as it's been hard to catch up, and thus my project of documenting everything. Honestly, I never did much discussing of this stuff on the perl6-language list, too much bikesheding there. I just wrote code instead, much more fun. A good portion of it is still buried in the Pugs distro and I would be happy to walk you through it one day, but honestly I am much happier with where Moose and Class::MOP are now, then the P6 stuff I did.
-stvn
| [reply] |
by John M. Dlugosz (Monsignor) on May 09, 2008 at 13:53 UTC | |