Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Ovid (2709)

Ovid
  (email not shown publicly)
http://publius-ovidius.livejournal.com/
AOL IM: ovidperl (Add Buddy, Send Message)

Stuff with the Perl Foundation. A couple of patches in the Perl core. A few CPAN modules. That about sums it up.

Journal of Ovid (2709)

Friday November 25, 2005
05:13 PM

Trying to implement runtime traits

[ #27745 ]

As it turns outs, implementing traits at runtime isn't too hard. It's the syntax which is killing me. Let's say that I have a new "Dog" object and I want my dog to do tricks. In Perl 6:

$fido does Tricks;

Class::Trait was not originally designed to support runtime trait composition so the does method either returns a list of traits a class can do or returns a boolean value indicating that a particular trait passed to it is avaiable. Thus, we use the apply method for adding traits. However, this raises a number of thorny issues. First, according to Synopsis 12, roles can be applied at runtime to both classes and instances and this will create a new anonymous class. For instances, this is easy. What does this mean for classes, though? I'm not sure. Bummer.

Applying them at runtime for instances is easier. I need to rebless an object into the appropriate anonymous class and flatten the trait methods into that class. However, I don't have an appropriate syntax. I could do this:

require Tricks;
my $fido = Dog->new;
Tricks->apply($fido);

Unfortunately, Synopsis 12 makes it clear that we should be able to apply several traits to fido at once, flattening them into a new anonymous class. The only way I can see to make that work is a variant of this:

Class::Trait->apply($fido, @list_of_traits);

That seems like a really ugly syntax. However, more than this, how would I then apply traits to a class? I could do this:

Class::Trait->apply(__PACKAGE__, @list_of_traits);

That seems like an even uglier syntax but I can't think of a better way. For the time being, runtime trait application seems best suited for instances, so I'll focus on that.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • Applying several traits to an instance should not do anything different than applying one. So for instance this (in pseudo Perl 6):

    $fido does Tricks does Treats;

    Would become this (in Perl 5 Traits):

    Treats->apply(Tricks->apply($fido));

    Basically apply should return the reblessed instance, and you just keep chaining them.

    Now, this may not be the most efficient approach, but I am not really sure that would matter since runtime application of multiple traits will probably be a rare occuranc

    • The better way to accomplish this (IMO of course) is to compose a third Trait out of the multiple traits you have applied, then apply that third trait to your instance.

      I think that’s the key to a bearable syntax: have a Class::Traits::compose, returning an anonymous trait which is a composition of the given traits, on which you then simply invoke apply:

      Class::Traits->compose( "Tricks", "Treats" )->apply( $fido );