I am trying to define a subroutine in Raku
whose argument is, say, an Array of Ints (imposing that as a constraint, i.e. rejecting arguments that are not Array
s of Int
s).
Question: What is the "best" (most idiomatic, or straightforward, or whatever you think 'best' should mean here) way to achieve that?
Examples run in the Raku
REPL follow.
What I was hoping would work
> sub f(Int @a) {1}
&f
> f([1,2,3])
Type check failed in binding to parameter '@a'; expected Positional[Int] but got Array ([1, 2, 3])
in sub f at <unknown file> line 1
in block <unit> at <unknown file> line 1
Another non-working example
> sub f(@a where *.all ~~ Int) {1}
&f
> f([1,2,3])
Constraint type check failed in binding to parameter '@a'; expected anonymous constraint to be met but got Array ([1, 2, 3])
in sub f at <unknown file> line 1
in block <unit> at <unknown file> line 1
even though
> [1,2,3].all ~~ Int
True
What does work
Both variations
> sub f(@a where { @a.all ~~ Int }) {1}
and
> sub f(@a where { $_.all ~~ Int }) {1}
do give me what I want:
> f([5])
1
> f(['x'])
Constraint type check failed in binding to parameter '@a'; expected anonymous constraint to be met but got Array (["x"])
in sub f at <unknown file> line 1
in block <unit> at <unknown file> line 1
I've used that in the past, but it strikes me as a bit clumsy/verbose..
Additional remark
The syntax Int @a
I initially tried isn't completely bogus, but I can't tell when it's supposed to go through and when not.
I can do this in a class for instance:
> class A { has Int @.a }
(A)
> A.new(a => [1,2,3])
A.new(a => Array[Int].new(1, 2, 3))
> A.new(a => [1,2,'x'])
Type check failed in assignment to @!a; expected Int but got Str ("x")
in block <unit> at <unknown file> line 1
Edit 1
As per the docs, this works
> sub f(Int @a) {1}
&f
> my Int @a = 1,2,3 # or (1,2,3), or [1,2,3]
> f(@a)
1
But if I omit the Int
in the declaration of @a
I get back to the errors reported before. And as noted, I can't run f
on anonymous arrays, with f([1,2,3])
.