Front page | perl.moose |
Postings from April 2012
Re: Role composition bug?
Thread Previous
|
Thread Next
From:
Fields, Christopher J
Date:
April 9, 2012 07:04
Subject:
Re: Role composition bug?
Message ID:
63B1F851-913A-4135-BA6C-6DAF740AC1FF@illinois.edu
On Apr 9, 2012, at 7:31 AM, Stevan Little wrote:
> On Apr 9, 2012, at 3:58 AM, Ovid wrote:
>
>>> ________________________________
>>> From: Jesse Luehrs <doy@tozt.net>
>>>
>>> On Sun, Apr 08, 2012 at 12:31:25PM -0700, Ovid wrote:
>>>> Hi all,
>>>>
>>>> I'm wondering if this is a known bug or a misunderstanding on my part (I assume the latter):
>>>>
>>>> use 5.10.0;
>>>> { package Role::A; use Moose::Role; with 'Role::C'; }
>>>> { package Role::B; use Moose::Role; with 'Role::C'; }
>>>> { package Role::C; use Moose::Role; with 'Role::D'; }
>>>> {
>>>> package Role::D;
>>>> use Moose::Role;
>>>>
>>>> sub foo {
>>>> my $proto = shift;
>>>> my $class = ref $proto // $proto;
>>>> return "$class\::foo";
>>>> }
>>>> }
>>>> package Consume;
>>>> use Moose;
>>>> with qw(Role::A Role::B);
>>>> say Moose->VERSION;
>>>> say Consume->foo;
>>>>
>>>> That prints out:
>>>>
>>>> 2.0402
>>>> Can't locate object method "foo" via package "Consume" at roles.pl line 19.
>>>>
>>>> Given that Role::C uses Role::D and the latter provides the 'foo()' method, that method should be provided to both Role::A and Role::B since they each consume Role::C. When consuming those roles, the Consume class should then have the 'foo()' method, but it does not.
>>>>
>>>> Did I misunderstand something? (For the curious, my Role::Basic module has the same bug).
>>>
>>> This is just a load order issue. 'with' happens at runtime, so when you
>>> say "with 'Role::C' in package Role::A, Role::C has no methods in it
>>> (since its "with 'Role::D'" hasn't executed yet). If you actually load
>>> things in the proper order, it just works (with no conflict, because all
>>> of the 'foo' methods are the same actual method). There is no bug here.
>>
>>
>> According to the definition of traits (I recognize that roles are similar to traits, but not identical), traits guarantee associativity by definition. That is to say:
>>
>> ( A + B ) + C = A + ( B + C )
>>
>> Thus, it's absolutely a bug for traits to exhibit different behavior depending on the order in which traits are defined or consumed. Since roles are not traits, is this documented?
>>
>>
>> See also: http://scg.unibe.ch/archive/papers/Scha02cTraitsModel.pdf, section 3.4, proposition 1.
>
> Right, but what Jesse is saying is that given the constraints of the Perl world that Moose must live in you have to load stuff in the right order. Here is a version of your script that actually works.
>
> use 5.10.0;
> {
> package Role::D;
> use Moose::Role;
>
> sub foo {
> my $proto = shift;
> my $class = ref $proto // $proto;
> return "$class\::foo";
> }
> }
> { package Role::C; use Moose::Role; with 'Role::D'; }
> { package Role::A; use Moose::Role; with 'Role::C'; }
> { package Role::B; use Moose::Role; with 'Role::C'; }
>
> package Consume;
> use Moose;
> with qw(Role::A Role::B);
> say Moose->VERSION;
> say Consume->foo;
>
> Jesse++ for stoping a second and thinking this one through.
>
> - Stevan
This might be a case worth documenting, though, if nothing more than to point out why this is necessary. That is, unless an example already exists...
chris
Thread Previous
|
Thread Next