Imagine a series of complex grammars represented as roles, although this simple example is enough to show the conflict:
role Alpha {
token alpha { :i <[A..Z]> }
}
role Digit {
token digit { <[0..9]> }
}
role Either
does Alpha
does Digit {
token either { <alpha> | <digit> }
}
grammar Thingy
does Either
does Alpha
{
token TOP { <alpha> <either>* }
}
my $match = Thingy.parse( '1a3' );
dd $match;
This doesn't work because Perl 6 doesn't untangle the relationships to figure out that the conflict is actually the same thing from the same source:
Method 'alpha' must be resolved by class Thingy because it exists in multiple roles
But, reading S14, I see:
A role may not inherit from a class, but may be composed of other roles. However, this "crony" composition is not evaluated until class composition time. This means that if two roles bring in the same crony, there's no conflict--it's just as if the class pulled in the crony role itself and the respective roles didn't. A role may never conflict with itself regardless of its method of incorporation.
I read that to mean that the roles are applied as late as possible, so the class Thingy
would be able to disentangle that Alpha
is included in two different parts. I figured this would work something like creating a list of all of the roles that would make up the final class, then applying that list only to the final class. That way, something like Either
would mix-in only the things it defined and would rely on the later composition to bring in Alpha
.
I ran across this when I was trying to implement grammars for various (IETF) RFCs. Many of them reference the grammars from other RFCs, which makes it impossible for Perl 6 to resolve inheritance by C3. So, I figured that roles would disconnect the relationships. Apparently it doesn't.
role A { method m {} }; role B does A {}; class C does A does B {}
. – raiph