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

Reply via email to