http://qs321.pair.com?node_id=901998


in reply to Re^2: Extensions via Moose
in thread Extensions via Moose

But, I'm still composing it before construction.

With MooseX::Traits, yes you are, however doing Role->meta->apply( $instance ) will let you do it after construction, as well the Moose::Util tools as well.

If I derive an anonymous class and then instantiate it, the amendment for C1 has to include instructions to make it change what it creates for C2 and C3.

I am not sure what you are asking here, are you looking for a trigger to be fired when C1 is reblessed into the anon-class? So that it will then do something with the C2 and C3 instances? If that is the case, no Moose does not provide that, however it would be pretty simple to just do yourself when the role is added to the C1 instance.

Now adding a role can do everything a traditional derived class can do, right? So there is no need to provide a mechanism to say "use this derived class instead of C2" in addition to the mechanism that lists all the roles that are to be applied to C2 at creation time.

When a role is applied to an instance, a new anon-class is created whose superclass is the old class (C2) and with the role added in. Then the instance is reblessed into that anon-class (see Class::MOP for all the reblessed MOP API). So, I believe I am answering your first question right when I say "Yes".

I could have the builder that instantiates C2 consult an attribute that says what roles to add to it, and the original plug-in added to that list. But, I don't like the idea of having a field that doesn't do anything except during object creation. There should be a more transient way to pass the information around.

I think I am missing a large part of your design, there are a bunch of ways to go about this, all different depending on your needs.

Maybe the builder can call something which gathers the trait's names, and the original plug-in can supply 'before' methods to grow that list. (But if I only have one instance anyway, all the extra code is worse than having a defunct slot!)

Well, the question really is, will it *always* just be one instance? As long as you don't get too carried away, it might be worth the extra effort to make it extensible.

Any more suggestions?

Like I said, there are many ways to go about this, runtime-roles (roles applied to an instance) are a powerful feature (thanks Perl 6!) and you can (ab)use them in lots of different ways. It all comes down to what is the best fit for your design.

-stvn

Replies are listed 'Best First'.
Re^4: Extensions via Moose
by John M. Dlugosz (Monsignor) on Apr 30, 2011 at 08:23 UTC
    I am not sure what you are asking here, are you looking for a trigger to be fired when C1 is reblessed into the anon-class?
    I did not think of that. I was supposing that whatever function wrapped the "pull in an extension" would apply a trait to C1, and then look up $instance->c2 and $instance->c3 and apply traits to them too.

    Basically, there are two approaches: (1) Create the extended class before creating the instance, and (2) Extend an existing instance.

    With (2), I can extend all the collaborators at the same time, using only logic within the function that loads and applies the extension.

    With (1), the extension of the top-level class needs to somehow change things so that when the collaborators are created, they are of the extended types too.

    Without a rebless hook, (2) needs to be wrapped by my code so I does all the steps; it can certainly call "lower level" Role->meta->apply as well. My original question was wondering if these had some syntactic sugar or more mature incarnations in another module already done (like Perl 6 "but" feature).

    But, I'm also supposing that I'm not breaking new ground in wanting an extension mechanism for a more complex case (not a single class, but functionality is broken up into smaller classes) and other people may have approached it already.

    As for my aversion to needless instance data, something I saw in MooseX::Traits raises another question. But I'll start a new post for that.

    Thanks for your patience.

    —John

      My original question was wondering if these had some syntactic sugar or more mature incarnations in another module already done (like Perl 6 "but" feature).

      No, there isn't any sugar. I think there are two reasons for that, 1) doing custom infix operators are pretty much impossible, 2) people don't mind the Role->meta->apply syntax that much (and 3, applying roles to instances is not all that commonly used a feature).

      But, I'm also supposing that I'm not breaking new ground in wanting an extension mechanism for a more complex case (not a single class, but functionality is broken up into smaller classes) and other people may have approached it already.

      Well, there is also MooseX::Object::Pluggable, but I think perhaps people are still exploring the possible features/complex-insanity that Moose and runtime-roles open up, so you probably have a lot of funky stuff out in the DarkPAN that has yet to reach the CPAN. Honestly, the Moose community on IRC is pretty active, I really think you would benefit from getting involved there.

      -stvn
Re^4: Extensions via Moose
by John M. Dlugosz (Monsignor) on Apr 30, 2011 at 09:06 UTC
    Hmm, the code in MooseX::Traits states
    # runtime role application is fundamentally broken. if you really # need it, write it yourself, but consider applying the roles before # you create an instance.
    And it is basically a call to:
    $trait->meta->apply($self, rebless_params => $rebless_params || {});
    So why should I be scared of Trait->meta->apply? Why would writing it myself be better than the function that appears here?
      Hmm, the code in MooseX::Traits states ...

      Not sure who wrote that comment, I suspect either Florian or Jonathan Rockway, I would not take that too much to heart, it is an opinion and a somewhat extreme one at that. It also may very well refer to an earlier state of that behavior, a lot of cleanup has taken place in that corner of the code base in the last few years.

      So why should I be scared of Trait->meta->apply?

      You shouldn't, but some people are scared off by the MOP (which is a good thing sometimes and a bad thing other times).

      Why would writing it myself be better than the function that appears here?

      Well, what is in MooseX::Traits has already been tested and is regularly tested against the Moose core with our smoke tester. But the code is basically just calls to Moose::Util functions, so I wouldn't worry about writing your own code too much.

      -stvn