Ovid,
I am not sure I like "includes". Personally I would approach this in
either one of two ways.
The "kinda brute force but not too bad performance wise since you
would only be doing it once at compile time"-way would be:
with 'My::Role' => { excludes => [ My::Role->meta-
>get_method_list ] };
Or, the better way, which would be to create a My::Role::Interface
module which is just a role full of C<requires 'method'> definitions.
Then your other roles can do My::Role::Interface, and your 10th class
can just do My::Role::Interface. This has the same benefits as sane
and correct usage of Java interfaces in that you now have a clearly
defined interface whose implementation can vary to your hearts
content. The performance impact of this extra role would also be
pretty minimal I think, certainly not enough that you would notice.
I am also very much not a fan of adding features to solve problems
that are easily solved in other ways. Moose already has a fairly large
feature set and I am pretty adverse to adding more unless they are
first vetted through a MooseX:: module (see the section on NEW
FEATURES in Moose::Manual::Contributing).
- Stevan
On Apr 28, 2009, at 3:53 AM, Ovid wrote:
There are times that you want to use a role, but only as an interface.
If 9 out of 10 classes use the implementation, it's annoying to have
that 10th class have to do this:
with 'My::Role' => { excludes => \...@a_long_list_of_methods };
What about something like this?
with 'My::Role' => { includes => [] };
That
would be the mutually exclusive opposite of 'excludes'. No methods
would be composed into your class, but they would all be added to the
'requires' list. This (I think) would largely overcome chromatic's
objection (http://use.perl.org/comments.pl?sid=42835&cid=68295)
that if someone wants to use a role as an interface, being forced to
manually exclude every method is annoying and would discourage role
use. So a role could be trivially used as an interface, if desired,
even if implementation is provided.
Plus, if you still needed two of the 8 methods a role provided:
with 'My::Role' => { includes => [qw{ foo bar }] };
Seems to me that this is the best of both worlds. This would also
make it trivial to add the "warn on conflict" back in because the
entire objection seemed to be that the warning coupled with it being
annoying to exclude all methods would discourage role use (an
argument which penalizes the programmer who values safety and
correctness, but then, Dominus doesn't like how we constantly
encourage "use strict", either). While I do realize I've lost this
argument, at least adding "includes" would make roles a tad more
flexible and make some of my work easier if I get around to writing
"MooseX::Role::Strict".
This
also shows what I *think* is a limitation in 'excludes'. All methods
listed in a role should be explicitly added to the 'requires' list.
The following is a runtime failure:
#!/usr/bin/env perl
package My::Role;
use Moose::Role;
sub foo { __PACKAGE__ }
package Bar;
use Moose;
with 'My::Role' => { excludes => 'foo' };
print Bar->foo;
# Can't locate object method "foo" via package "Bar" at role.pl
line 13.
Thoughts?
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