Consider
subset MySubset of Str where * ~~ /^ \d $<interesting> = ( \d+ ) $/;
Now I want to use the subset as a Type in my signature, but put the captured part(s) into a variable via unpacking, kinda like
sub f( MySubset $( :$interesting ) )
{
say $interesting;
}
f( "12345678" ); # should say 2345678
That's not working of course. Is it even possible to do this?
Subsignature unpacking is about turning a value into a Capture
and matching against that.
class Point {
has ( $.x, $.y );
}
my ( :$x, :$y ) := Point.new( x => 3, y => 4 ).Capture;
say "[$x,$y]"; # [3,4]
Since a Str
doesn't have a public attribute named $.interesting
, it won't match.
A subset is just extra code to check a value more completely than you could otherwise do. It does not turn the value into a new type.
It would be more likely to work if you used $<interesting>
.
sub f( MySubset )
{
say $<interesting>;
}
Of course since blocks get their own $/
, this also does not work.
While it might be nice to pass information from a subset to a signature, I am not aware of anyway to do it.
As a side note, where
already does smart matching so it is an incredibly bad idea to use ~~
inside of it.
This is basically how your subset works:
"12345678" ~~ ( * ~~ /…/ )
In this particular case you could just use .substr
sub f( MySubset $_ ) {
.substr(1)
}
I can't figure out a way with a subset
type, however there is a way - with a little...creativity - to do a match and unpack it in the signature.
Match
inherits from Capture
, so having one be unpacked in a signature is straightforward - if only we can arrange for there to be a parameter that contains the Match
we wish to unpack. One way to do that is to introduce a further parameter with a default. We can't really stop anyone passing to it - though we can make it a pain to do so by using the anonymous named parameter. Thus, if we write this:
sub foo($value, :$ (:$col, :$row) = $value.match(/^$<col>=[<:L>+]$<row>=[\d+]$/)) {
say $col;
say $row;
}
And call it as foo("AB23")
, the output is:
「AB」
「23」
Finally, we may factor the rule out to a named token, achieving:
my token colrow { ^$<col>=[<:L>+]$<row>=[\d+]$ }
sub foo($value, :$ (:$col, :$row) = $value.match(&colrow)) {
say $col;
say $row;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With