Sorry for the top-post. I thought it was appropriate here as I've nothing I 
want to say on a particular basis other than "thank you" for a such a detailed, 
thoughtful answer.  I appreciate it :)

 
Cheers,
Ovid
--
Buy the book         - http://www.oreilly.com/catalog/perlhks/
Tech blog            - http://use.perl.org/~Ovid/journal/
Twitter              - http://twitter.com/OvidPerl
Official Perl 6 Wiki - http://www.perlfoundation.org/perl6



----- Original Message ----
> From: Stevan Little <stevan.lit...@iinteractive.com>
> To: Ovid <publiustemp-catal...@yahoo.com>
> Cc: moose@perl.org
> Sent: Thursday, 16 July, 2009 5:57:25
> Subject: Re: Bug with Moose::Role attributes
> 
> Hey Ovid,
> 
> On Jul 15, 2009, at 2:24 PM, Ovid wrote:
> > On the Perl 6 language list, Raphael Descamps posted a link to a paper 
> explaining how to implement stateful traits 
> (http://scg.unibe.ch/archive/papers/Berg07eStatefulTraits.pdf). One of the 
> authors of that paper worked on the original traits paper and the research 
> appears solid.
> 
> I was actually approached by the authors of this paper before it was 
> published 
> but after they had finished the implementation. They were wondering how we 
> handled attribute conflicts in Perl 6/Moose. In Moose we will die on an 
> attribute conflict, this is basically punting because the this problem is 
> very 
> hard. I explained to them though that Moose attributes were significantly 
> more 
> complex then Smalltalk attributes so our more extreme solution was not really 
> applicable to them. Moose attributes are truly first class citizens of the 
> MOP 
> layer while Smalltalk simply has a list of slots in the instance and accessor 
> methods that are (IIRC) totally unrelated to them on any formal level.
> 
> See the problem is that we (Moose) don't just have reader/writer methods to 
> worry about, but we have reader/writer or accessor, predicate methods, 
> clearer 
> methods, associated builder and lazy_build methods and then the possibility 
> of 
> delegation methods with handles. The result is that we have a *LOT* of things 
> to 
> check, and we don't want to just test this once on creation of the attribute, 
> but we actually need to compare the attribute to *every other attribute* the 
> class (and it's superclasses) have. This is the only way to be sure that we 
> are 
> not creating a conflict with a method that is somehow tied to an attribute 
> and 
> therefore to state.
> 
> >  Basically, it argues that traits need to have private accessors.
> 
> Yeah, this is something I remember discussing with chromatic, Luke Palmer and 
> Audrey at YAPC::NA in Toronto. We kept going around and around on this never 
> coming to a totally satisfying solution. It basically always felt (to me 
> anyway) 
> that it was hiding the problem instead of actually dealing with it. Although 
> I 
> have not read the paper yet, so perhaps when i see their reasoning I might 
> feel 
> different.
> 
> Also note that (at least some) of the authors or this paper expressed to me 
> that 
> they were not happy with this outcome. That having privacy in Smalltalk felt 
> very un-Smalltalk-ish and so the solution kind of felt dirty. I feel the same 
> way about this in regards to Perl, the idea of requiring privacy seems very 
> un-Perlish.
> 
> >  I won't go into full detail (you'll have to read the paper), but I decided 
> > to 
> see exactly how Moose handles this.  I *think* this is a bug in Moose 0.87, 
> but 
> I'm unsure.
> 
> Nope, this is a bug in Moose 0.01 (or whatever version it was we introduced 
> roles in).
> 
> > 
> 
> > I would suggest a couple of things.
> > 
> > 1.  A class's attributes should silently override a role's attributes (I 
> > hate 
> this, but it's in keeping with what Moose does with class/role methods).
> 
> The problem with this is that many of the roles methods will likely expect 
> the 
> attribute (and it's associated methods) to be there, so silently overriding a 
> role attribute is pretty much totally out of the question. While kinda 
> annoying 
> we do the only sensible thing here, which is to die.
> 
> > 2.  A class's methods MUST fail when trying to override a role's 
> > attributes, 
> thus forcing deliberate exclusion.  This is because methods and attributes 
> serve 
> such radically different purposes that a failure here is warranted.
> 
> Yes, I will agree here, but as of right now role attributes are not first 
> class 
> citizens so this is not possible. There was a lot of talk at this years 
> YAPC::NA 
> hackathon about actually making them first class, so rest assured it is being 
> addressed.
> 
> > 3.  A class's attributes MUST fail when trying to override a role's methods 
> (see above).
> 
> Same as #2, I agree with you, but until we have first class role attributes 
> and 
> can calculate the methods they will create at composition time, we won't be 
> able 
> to fix this.
> 
> > I expect that people will have different views, but that's OK.  Have fun 
> > with 
> that.
> 
> Well not me, except for the first item, which I suspect if you read my point 
> there you will agree with me on.
> 
> > I would also love to see private attributes available for Moose roles.
> 
> Yuk! I would prefer to solve the problem without them if possible. Privacy in 
> perl is hackish at best since you cannot really properly hide a method from 
> the 
> dispatcher (just die-ing when called from an improper context is *NOT* 
> correct 
> privacy, true privacy means that the method is invisible to the dispatcher 
> and 
> not present in the MRO).
> 
> > Right now, that attribute in the role unnecessarily clutters the interface 
> > of 
> the class and there's no need for that.
> 
> Unless of course that is the purpose of the role, to include an attribute. 
> Sure 
> I can see occasions when you do want to hide data, but it is not always the 
> case 
> and I would argue is more an exception then it is a rule.
> 
> > Plus, the class shouldn't have to provide an attribute which only that role 
> uses because that violates the role's encapsulation.
> 
> I think that the roles encapsulation has already been violated when it was 
> completed taken apart and all it's component bits shoved (composed) in the 
> class. Again, there is a case for data-hiding in some cases, but certainly 
> not 
> all.
> 
> So, now that is out of the way, let me explain the rough plan that Yuval 
> Kogman 
> and I have been tossing around now for almost 3 years.
> 
> Class::MOP needs some kind of low level "trait"-like mechanism (in this 
> context 
> "trait" means the things in the original traits paper, which is just sets of 
> pure methods and the composition rules that apply to them). These would be 
> primarily an internally used feature too and not something exposed in the 
> Moose 
> sugar. Lets call these "mop-traits" for now to avoid any confusion.
> 
> Now, lets start with just classes first.
> 
> The idea is that an attribute meta-object can actually produce one of these 
> "mop-traits" for itself. The result is a trait which defines all the methods 
> that would be associated with this particular attribute. This would includee 
> the 
> reader/writer/accessor, predicate, clearer and delegated methods for handles, 
> as 
> well as required methods for the builder/lazy_build methods.
> 
> So then when a class is being composed, it asks each attribute (local and 
> inherited) to supply a mop-trait. It then takes all these mop-traits and 
> composes them all together into a single composite trait, applying all the 
> conflict resolution rules you would expect. The result is that we would be 
> able 
> to tell at this point if any of our attributes conflict with one another.
> 
> Next we would ask the class itself to create a mop-trait of itself to 
> represent 
> all the methods (local and inherited) and we compose it with the attribute 
> composite trait. We do this because we want to apply trait-style conflict 
> detection and not class conflict detection (where the local class would win 
> and 
> superclass would loose, etc).
> 
> The end result is that we are assured that no attributes conflict with one 
> another and no attribute created methods conflict with hand-defined methods.
> 
> Sounds nice doesn't it :)
> 
> It is also very expensive. Liberal use of caching and possibly doing the 
> mop-trait composition with something more optimized like Set::Object would 
> perhaps help, but this is all compile time cost and we already have a problem 
> with that in Moose. And just wait, it gets worse, we haven't even gotten to 
> roles yet.
> 
> So, now throwing roles into the mix.
> 
> A role attribute is a deferred attribute, meaning that it really has very 
> little 
> value (besides introspection maybe) until it is added into the class into 
> which 
> it is being composed. It also is context sensitive, different composition 
> contexts can produce different results (parameterized roles, etc).
> 
> We would need to break down all the roles into sets of mop-traits in the same 
> was a the classes (first each of the attributes, then the methods). This 
> isn't 
> as bad for roles since they are already flattened and have no indirection to 
> resolve. This would assure us that each single role itself would be 
> internally 
> consistent.
> 
> We would then need to compose all these roles together (assuming your 
> composing 
> multiple roles into your class) so that we could be sure that this particular 
> combination of roles is valid and non-conflicting.
> 
> Then we would need to take all the mop-traits of our roles and compose them 
> with 
> all the mop-traits of our class (it's attributes and methods, as discussed 
> above), and let me tell you, that there is a whole mess-a composin' going on.
> 
> A conflict in this process would basically signal a composition problem, and 
> if 
> we add some more error context info to the required methods that are produced 
> by 
> these conflicts we should be able to give some pretty good error messages, 
> especially since we wont have to die at the first sign of error.
> 
> Now, again, we certainly will be able to cache things, especially if we can 
> keep 
> mop-trait composition as a pure (side-effect free) computation.
> 
> ...
> 
> So at this point when you call ->new on your class, it should shoot rainbows 
> out 
> of your computers USB drive and a unicorn should then appear and give you ice 
> cream (or some kind of frozen tofu treat if your are lactose intolerant or a 
> vegan).
> 
> ---
> 
> Now, I will be honest, I highly doubt you will see this in Moose 1.0, to do 
> it 
> right would really require a major overhaul in how things work right now and 
> would almost surely require us to be able to "compile" Moose classes (to .pmc 
> files or something). Yuval explored a lot of these ideas (and a more 
> compile-able meta-model) in his MO experiement, but that remains just a 
> research 
> project at this point. Yuval and I are still pondering this along with the 
> rest 
> of the Moose crew, so have faith.
> 
> - Stevan

Reply via email to