Type captures are a cool thing to use for even some simple stuff:
sub assert-same(::T $a, T $b) { ; }
assert-same 1, 2; # silent
assert-same 1, "a"; # type check error
However, the result is non-intuitive for positionals. If I have the following signature
sub foo(Str @bar, Str @xyz) { ; }
Then @bar
is a positional whose elements must be Str
, as is @xyz
. But if I use a type capture, things go weird:
sub assert-same(::T @a, T @b) { ; }
my Str @x = <i j>;
my Str @y = <x y>;
assert-same @x, @y;
# Type check failed in binding to parameter '@b';
# expected Positional[Array[Str]] but got Array[Str] (Array[Str].new("x", "y"))
It seems that the first type capture is capturing via .WHAT
(which makes sense for scalars) rather than .of
which to me is the intuitive sense for positionals, given that the immediate reuse of the capture would only work if .of
had been originally used.
This smells of a bug, but if it's by design, is there a way to enforce via type capture that two typed positionals have elements that are of the same type? In the meantime, I can use
sub assert-same(::T @a, @b where .all ~~ @a.of ) { ; }
my Str @x = <a b c>;
my Str @y = <x y z>;
my Int @i = 1,2,3;
assert-same @x, @y; # silent
assert-same @x, @i; # type check
But that seems a bit silly.