There seems to be a problem in using the signature given to a role in the roles you want to mix-in. Minimal example:
#!/usr/bin/env perl6
role by-n[$n=1] {
method multiply(Str $str) { return $str x $n; }
}
role by-string[$n=1] does by-n[$n] {
method whatever(Str $str) { return $n ~ "→" ~ $.multiply( $str ); }
}
class mighty-þor does by-string[2] {};
say mighty-þor.whatever("*");
This returns an error, which seems to indicate $n
has a Mu
type:
Cannot resolve caller infix:<x>(Str, Mu); none of these signatures match:
()
($x)
($s, Num:D $n)
($s, Any:D $n)
($s, Any:U $n)
(Str:D $s, Int:D $repetition --> Str:D)
(str $s, int $repetition --> str)
in method multiply at composable-roles-fail.p6 line 4
in method whatever at composable-roles-fail.p6 line 8
in block <unit> at composable-roles-fail.p6 line 13
However, role by-string[$n=1] does by-n[1]
or any other number works well. Trying to fix the type in the signature:
role by-n[Int $n=1] {
method multiply(Str $str) { return $str x $n; }
}
role by-string[Int $n=1] does by-n[$n] {
method whatever(Str $str) { return $n ~ "→" ~ $.multiply( $str ); }
}
yields a different error:
===SORRY!=== Error while compiling /home/jmerelo/Code/perl6/dev.to-code/perl6/composable-roles-fail.p6
No appropriate parametric role variant available for 'by-n'
at /home/jmerelo/Code/perl6/dev.to-code/perl6/composable-roles-fail.p6:11
While, once again, changing it to role by-string[Int $n=1] does by-n[1]
works. Any idea of what's going on here or what can be done to fix this?
My conclusion is that this is a bug, or at least an NYI.
The problem is that the $n
in by-string
isn't really set until the role is actually composed into a class. However, the adding of the role by-n
happens at compile time of the by-string
role. At which time we don't know the value it will get when by-string
is composed.
So, for this to work, we would need to delay the adding of the by-n
role to the by-string
role until the by-string
role is composed. And that's not how it's currently implemented, afaics.
I'm pretty sure there is a ticket for this already. But to be sure this doesn't fall through the cracks, you should maybe open a GitHub issue.
Meanwhile, the only way I see around this at the moment, is to copy the methods of the by-n
role manually to the by-string
role.
Wish I had better news for you.