Right now, I have a MAIN
sub that can take one or more string arguments. But I am using two separate parameters for MAIN
to do it:
sub MAIN (
Str:D $file,
*@files,
) {
@files.prepend: $file;
# Rest of the program
}
Now I am wondering if there's a more idiomatic way to achieve this, as my current solution feels a little clunky, and not very Perly.
You could do it with a proto sub
proto sub MAIN ( $, *@ ){*}
multi sub MAIN ( *@files ) {
# Rest of the program
}
or with sub-signature deparsing
sub MAIN ( *@files ($,*@) ) {
# Rest of the program
}
At the risk of "over answering" - my take on "Perly" is concise as possible without becoming obscure (perhaps I'm just replacing one subjective term with two others... :-)
If you have a "slurpy" array as the only parameter, then it will happily accept no arguments which is outside the spec you put in the comments. However, a positional parameter is compulsory by default and proto's are only necessary if you want to factor out constraints on all multi's - presumably overkill for what you want here. So, this is enough:
sub MAIN($file , *@others) {
say "Received file, $file, and @others.elems() others."
}
This is close to what mr_ron put - but why not go with the default Usage message that MAIN kindly whips up for you by examining your parameters:
$ ./f.pl
Usage:
./f.pl <file> [<others> ...]
Some might say I cheated by dropping the Str type constraint on the first parameter but it really doesn't buy you much when you're restricting to strings because numerics specified at the CLI come through as type IntStr (a kind-of hybrid type) that satisfies a Str constraint. OTOH, when constraining CLI parameters to Num or Int, Perl6 will check that you're actually putting digits there - or at least, what unicode considers digits.
If you're wanting actual filenames, you can save yourself a validation step by constraining to type IO()
. Then it will only work if you name a file. And finally, putting where .r
after the parameter will insist that it be readable to boot:
sub MAIN(IO() $file where .r, *@others) { ...
One short line that insists on one compulsory argument that is a filename referencing a readable file, with a varying number of other parameters and a useful Usage message auto generated if it all goes sideways...
Perhaps good enough answer here:
sub MAIN(*@a where {.elems > 0 and .all ~~ Str}) {
say "got at least 1 file name"
}
sub USAGE {
say "{$*PROGRAM-NAME}: <file-name> [ <file-name> ... ]"
}
Based on docs here: https://docs.perl6.org/type/Signature#Constraining_Slurpy_Arguments
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