Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

nested roles are badly limited

3 views
Skip to first unread message

John Macdonald

unread,
Nov 21, 2014, 4:45:02 PM11/21/14
to mo...@perl.org
If a role specifies a requires value, that value must be provided in the consuming class.

It cannot be provided in a consuming role.

It cannot be provided in a separate role that is loaded earlier in the same with statement.

It can only be provided in the parent class directly, or in a role consumed by the parent class in an earlier with statement.

That means that you cannot provide a role that bundles up a bunch of roles to make it easy to get the *right* collection loaded in the *right* order by all end consumers.  The separate with statement issue means that you lose the cross-checking done by loading multiple roles in the same with statement.

Without looking into the internals of Roles, I suspect that the attributes of a role are not installed into the consuming class until after the entire role has been processed (which means that a with inside the role is processed too soon, as well as being processing in the namespace of the consuming role rather than the final consuming class).

Is there a good way to work around this?

$ for i in *; do     echo ==== cat $i;     cat $i;     echo ====;     echo ==== perl $i;     perl $i; done
==== cat test1.pl
package BRole;
use Moose::Role;

requires 'b';

package ARole;
use Moose::Role;

has 'b' => ( is => 'ro', isa => 'Scalar' );

package main;
use Moose;
with 'ARole', 'BRole';
====
==== perl test1.pl
'ARole|BRole' requires the method 'b' to be implemented by 'main' at /oicr/local/boutroslab/sw/NightlyBuilds/2014-11-21/perl/Perl-BL-2014-11-21/lib/site_perl/5.18.2/x86_64-linux/Moose/Exporter.pm line 418
    Moose::with('ARole', 'BRole') called at test1.pl line 13
==== cat test2.pl
package BRole;
use Moose::Role;

requires 'b';

package ARole;
use Moose::Role;

has 'b' => ( is => 'ro', isa => 'Scalar' );
with 'BRole';

package main;
use Moose;
with 'ARole';
====
==== perl test2.pl
'ARole' requires the method 'b' to be implemented by 'main' at /oicr/local/boutroslab/sw/NightlyBuilds/2014-11-21/perl/Perl-BL-2014-11-21/lib/site_perl/5.18.2/x86_64-linux/Moose/Exporter.pm line 418
    Moose::with('ARole') called at test2.pl line 14
==== cat test3.pl
package BRole;
use Moose::Role;

requires 'b';

package ARole;
use Moose::Role;

has 'b' => ( is => 'ro', isa => 'Scalar' );

package main;
use Moose;
with 'ARole';
with 'BRole';
====
==== perl test3.pl


John Macdonald
Software Engineer

Ontario Institute for Cancer Research
MaRS Centre

661 University Avenue

Suite 510
Toronto, Ontario

Canada M5G 0A3

Tel:

Email: John.Ma...@oicr.on.ca

Toll-free: 1-866-678-6427
Twitter: @OICR_news


www.oicr.on.ca

This message and any attachments may contain confidential and/or privileged information for the sole use of the intended recipient. Any review or distribution by anyone other than the person for whom it was originally intended is strictly prohibited. If you have received this message in error, please contact the sender and delete all copies. Opinions, conclusions or other information contained in this message may not be that of the organization.

mo...@hidden-primary.net

unread,
Nov 22, 2014, 6:00:02 AM11/22/14
to mo...@perl.org
Hej John,

Am 21.11.2014 um 22:32 schrieb John Macdonald:
> ==== cat test1.pl
> package BRole;
> use Moose::Role;
>
> requires 'b';
>
> package ARole;
> use Moose::Role;
>
> has 'b' => ( is => 'ro', isa => 'Scalar' );
>
> package main;
> use Moose;
> with 'ARole', 'BRole';
> ====

just change it to this:

package BRole;
use Moose::Role;

requires 'b';

package ARole;
use Moose::Role;

has 'b' => (is => 'ro', isa => 'Scalar');

package main;
use Moose;
with 'ARole';
with 'BRole';

And you're done.

Kind regards

--
Marco

John Macdonald

unread,
Nov 22, 2014, 9:00:02 AM11/22/14
to mo...@hidden-primary.net, mo...@perl.org
Yes, that was one of my three examples.

Doing it that way means there are two problems:

1. ARole cannot encapsulate the entire interface - every consumer of ARole has to explicitly consume ARole and BRole. Not only that, every consumer of ARole has to consume them in the right order - they have to support the internal implementation detail of ARole in two different ways that a fully encapsulated interface would hide completely. Suppose ARole is updated to use an alternate BPlusRole for its needs - now you have to find every consumer of ARole and change how they load ARole.

2. Additionally, every consumes has to consume ARole and BRole in two separate "with" statements - losing the cross-checking that with provides (for conflicting method/attribute names).

John Macdonald
Software Engineer

Ontario Institute for Cancer Research
MaRS Centre

661 University Avenue

Suite 510
Toronto, Ontario

Canada M5G 0A3


Tel:

Email: John.Ma...@oicr.on.ca

Toll-free: 1-866-678-6427
Twitter: @OICR_news


www.oicr.on.ca

This message and any attachments may contain confidential and/or privileged information for the sole use of the intended recipient. Any review or distribution by anyone other than the person for whom it was originally intended is strictly prohibited. If you have received this message in error, please contact the sender and delete all copies. Opinions, conclusions or other information contained in this message may not be that of the organization.

________________________________________
From: mo...@hidden-primary.net [mo...@hidden-primary.net]
Sent: November 22, 2014 5:42 AM
To: mo...@perl.org
Subject: Re: nested roles are badly limited

0 new messages