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
Stories, comments, journals, and other submissions on use Perl; are Copyright 1998-2006, their respective owners.
Class::Role (Score:2)
Re:Class::Role (Score:2)
Note that in the following that I do not use the word "role" even though that's the Perl 6 term. This is deliberate to make it clear I'm only talking about Perl 5 traits. Even when I discuss Class::Role I'll call it a trait. Yes, I know that's awkward :)
Well, first and foremost, Class::Trait [cpan.org] is the only Perl module to have a substantially complete implementation of traits as described in the classic "traits paper [unibe.ch]" that introduced most programmers to traits.
As for Class::Role, it appears to have the same bug which Perl6::Roles also has and which Class::Trait just fixed.
Namely, it grabs all code in a package without checking to see whether or not that code actually should be flattened into the parent class (I'd write a test script to verify this but I couldn't get Class::Role to work on my box. Have you used it?) Class::Roles gets around that by requiring a role definition to list which methods are provided. I like that but I didn't want to change the Class::Trait interface.Let's look at the sample trait at the top of the documentation for Class::Role:
Where does the name() method come from? In the example code, that's provided in the class using the trait. That's a problem, though. If that method doesn't exist, it's a run-time error. Further, if you never call the profess() method in your code, you won't discover the bug. It would be awful if a critical production system uncovers the bug after your code goes "live".
Here's how that would be written with Class::Trait:
Now, if name() does not exist in the calling class (either directly or from some other trait being used), your code won't even compile.
requirement (name) for LongLiver not in Donkey
I believe that Class::Trait is the only Perl trait implementation which implements this. Further, if you read the traits paper, I believe it's critical that this feature be present. Here are the major features that Class::Trait is designed to support:
I do have more plans for Class::Trait but for right now it's fairly feature complete. My major concern is to make "deferred" methods available. That is, a class or trait should be able to "promise" a method and, even if it doesn't exist at compile time, it's "promised" to exist when called. This should make Class::Trait more Perlish.
Reply to This
Parent
Runtime role (trait) composition (Score:1)
Name::Of::Role->apply( $some_object_of_unknown_class );
Can (does/will) Class::Traits support that?
Re:Runtime role (trait) composition (Score:2)
It's possible that it will. For the time being, I'm doing some deep internals work with it to make sure that I have everything nailed down. After I feel truly comfortable with its current state I'll start expanding it.
Re:Runtime role (trait) composition (Score:1)
Re:Runtime role (trait) composition (Score:2)
Currently there is a workaround:
That will properly use those traits, report conflicts, etc. However, it only works once. If both of those traits have identically named methods, the initialize() will fail. The following will not work:
This is because by the time the second trait is used, the meta information for the firs
Re:Runtime role (trait) composition (Score:1)
eval sprintf "package %s; Class::Trait->apply(%s);",
ref $some_object_of_unknown_class, $trait_class;
whereas I'd like to be able to do:
$trait_class->apply( $some_object_of_unknown_class );
(which would rebless $some_object_of_unknown_class into a new clas
Re:Runtime role (trait) composition (Score:1)
I just wanted to add a thank you for working on this.
Re:Runtime role (trait) composition (Score:2)
This is where I'm not sure I'm following you. It sounds like what you want is prototyped OO whereby one can add new methods to an instance and not just to the class itself, is that correct? However, I'm not sure that your syntax is good. How would that chai
Re:Runtime role (trait) composition (Score:2)
D'oh! Even better:
With that, a class with a runtime trait applied will have subsequent runtime traits overriding methods in the same anonymous class. The heirarchy is flatter, we use a LIFO strategy for trait method flattening, performance is better and (I think) behavior is the
Re:Runtime role (trait) composition (Score:1)
Yes. Or more specifically, I want to get as close to S12 as possible. I'm hoping you can follow the Perl6 approach to roles ( http://dev.perl.org/perl6/doc/design/syn/S12.html#roles [perl.org]) as closely as practical.
S12 says compile-time composition merges into one class and detects collisions (as Class::Trait does now), but r
Re:Runtime role (trait) composition (Score:2)
I don't see $biffo reusing part of the class tree for a few reasons. First, I am hoping to not layer on more than on anonymous class, though I might. Instead, I was hoping to add one anonymous class layer and flatten new traits in that class. That makes things really, really simple. However, there's a catch. If I can apply a trait, I should be able to remove it, too. That means that having a chain of anonymous classes may be the way to go (as removing a trait would effectively be like removing an item
Re:Runtime role (trait) composition (Score:1)
S12 does say You can also mixin a precomposed set of roles:
$fido does Sentry | Tricks | TailChasing | Scratch;
This will level the playing field for collisions among the new set of roles, and guarantees the creation of no more than one more anonymous class.
That sounds like it matches what you're proposing (a single anon class
Re:Class::Role (Score:2)
We are using Class::Role in a very large production system. There were never any problems in installing it.
You make some very good points about traits there. I was probably thinking too much in terms of "smart Java interfaces" to see the whole power of traits. The reason we originally chose to use Class::Role was the name. I really like the term role, because it creates nice pictures in my head :).
Basically the only thing we are using roles for at the moment is to implement methods which are empty in th
Re:Class::Role (Score:2)
Are you saying, in your example above, that "Entity" is effectively a Java interface and "Historian" provides the implementations? If so, that's a very interesting way of going about things. I'll have to think about that.
Re:Class::Role (Score:2)
Re:Class::Role (Score:2)
By the way: The same deficiency could be pointed out about the base pragma. If it would call import on the super class, an abstract super class could enforce its child the implement certain methods.
I don't know if Class::Trait implements this, but it should be possible for a class that uses a trait to declare that it it is also a trait or abstract class that requires certain methods to be implemented by child classes. If both traits require a "name" method to be implemented, that should not be a compile t
Re:Class::Role (Score:2)
it should be possible for a class that uses a trait to declare that it it is also a trait or abstract class that requires certain methods to be implemented by child classes.
If I understood you correctly, it sounds like you're asking for traits to be composed of other traits and for all of those traits to specify required methods even if the composite of all of those traits does not provide them, thus requiring the class using the traits to make them available. If that is what you mean, then yes, Class:
Re:Class::Role (Score:1)
Re:Class::Role (Score:1)