Hi all,
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. Basically, it argues that traits need to have private
accessors. 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.
Consider the following code. Now that the role provides an attribute named
"counter" and the class using the role provides a method of the same name. The
methods are not semantically equivalent, so I had two expectations, possibly
due to me misunderstanding Moose:
1. The class method would silently override the role attribute.
2. This code would break horribly.
#!/usr/bin/env perl -l
{
package MyRole;
use Moose::Role;
has counter => ( is => 'rw', default => 0 );
sub inc {
my $self = shift;
$self->counter( $self->counter + 1 );
return $self->counter;
}
}
{
package Foo;
use Moose;
with 'MyRole';
sub counter { 'this is the counter' }
}
my $foo = Foo->new;
print $foo->inc for 1 .. 5;
print $foo->counter;
However, my expectations were wrong. Here's the output when run:
1
2
3
4
5
5
In other words, the class's counter() method was silently discarded, denying
the class the ability to control its behavior.
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).
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.
3. A class's attributes MUST fail when trying to override a role's methods
(see above).
I expect that people will have different views, but that's OK. Have fun with
that.
I would also love to see private attributes available for Moose roles. Right
now, that attribute in the role unnecessarily clutters the interface of the
class and there's no need for that. Plus, the class shouldn't have to provide
an attribute which only that role uses because that violates the role's
encapsulation.
There's more I can say, but dinner's beckoning. I highly recommend the paper
linked to above.
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