如何在 MAIN 中要求一个或多个参数
How to require 1 or more of an argument in MAIN
现在,我有一个 MAIN
sub 可以接受一个或多个字符串参数。但是我为 MAIN
使用了两个单独的参数来做到这一点:
sub MAIN (
Str:D $file,
*@files,
) {
@files.prepend: $file;
# Rest of the program
}
现在我想知道是否有更惯用的方法来实现这一点,因为我目前的解决方案感觉有点笨拙,而且不是很 Perly。
也许这里的答案足够好:
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> ... ]"
}
基于此处的文档:
https://docs.perl6.org/type/Signature#Constraining_Slurpy_Arguments
您也可以尝试使用简单的动态变量:
die "Usage: $*EXECUTABLE <file> <file2>*" if !+@*ARGS;
my @files = @*ARGS;
其中 @*ARGS
是 an array with the arguments issued into the command line
你可以用 proto sub
proto sub MAIN ( $, *@ ){*}
multi sub MAIN ( *@files ) {
# Rest of the program
}
sub MAIN ( *@files ($,*@) ) {
# Rest of the program
}
冒 "over answering" 的风险 - 我对 "Perly" 的看法尽可能简洁而不晦涩(也许我只是用另外两个主观术语替换了一个... :-)
如果你有一个 "slurpy" 数组作为唯一的参数,那么它会很乐意接受任何超出你在评论中输入的规范的参数。但是,默认情况下位置参数是强制性的,并且 proto's 仅在您想排除对所有 multi 的约束时才是必需的 - 可能对您在这里想要的东西有点矫枉过正。所以,这就足够了:
sub MAIN($file , *@others) {
say "Received file, $file, and @others.elems() others."
}
这与 mr_ron 的内容很接近 - 但为什么不使用 MAIN 通过检查您的参数为您提供的默认用法消息:
$ ./f.pl
Usage:
./f.pl <file> [<others> ...]
有些人可能会说我通过在第一个参数上删除 Str 类型约束来作弊,但是当您限制为字符串时它确实不会给您带来太多好处,因为数字指定在CLI 以满足 Str 约束的 IntStr 类型(一种混合类型)的形式出现。 OTOH,当将 CLI 参数限制为 Num 或 Int 时,Perl6 将检查您是否实际将数字放在那里 - 或者至少,unicode 认为数字是什么。
如果您想要实际的文件名,您可以通过强制输入 IO()
来节省验证步骤。那么它只会在你命名一个文件时起作用。最后,将 where .r
放在参数之后将坚持它是可读的:
sub MAIN(IO() $file where .r, *@others) { ...
坚持一个强制性参数的短行,该参数是一个引用可读文件的文件名,具有不同数量的其他参数和一条有用的使用消息,如果它全部出现问题,则会自动生成...
现在,我有一个 MAIN
sub 可以接受一个或多个字符串参数。但是我为 MAIN
使用了两个单独的参数来做到这一点:
sub MAIN (
Str:D $file,
*@files,
) {
@files.prepend: $file;
# Rest of the program
}
现在我想知道是否有更惯用的方法来实现这一点,因为我目前的解决方案感觉有点笨拙,而且不是很 Perly。
也许这里的答案足够好:
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> ... ]"
}
基于此处的文档: https://docs.perl6.org/type/Signature#Constraining_Slurpy_Arguments
您也可以尝试使用简单的动态变量:
die "Usage: $*EXECUTABLE <file> <file2>*" if !+@*ARGS;
my @files = @*ARGS;
其中 @*ARGS
是 an array with the arguments issued into the command line
你可以用 proto sub
proto sub MAIN ( $, *@ ){*}
multi sub MAIN ( *@files ) {
# Rest of the program
}
sub MAIN ( *@files ($,*@) ) {
# Rest of the program
}
冒 "over answering" 的风险 - 我对 "Perly" 的看法尽可能简洁而不晦涩(也许我只是用另外两个主观术语替换了一个... :-)
如果你有一个 "slurpy" 数组作为唯一的参数,那么它会很乐意接受任何超出你在评论中输入的规范的参数。但是,默认情况下位置参数是强制性的,并且 proto's 仅在您想排除对所有 multi 的约束时才是必需的 - 可能对您在这里想要的东西有点矫枉过正。所以,这就足够了:
sub MAIN($file , *@others) {
say "Received file, $file, and @others.elems() others."
}
这与 mr_ron 的内容很接近 - 但为什么不使用 MAIN 通过检查您的参数为您提供的默认用法消息:
$ ./f.pl
Usage:
./f.pl <file> [<others> ...]
有些人可能会说我通过在第一个参数上删除 Str 类型约束来作弊,但是当您限制为字符串时它确实不会给您带来太多好处,因为数字指定在CLI 以满足 Str 约束的 IntStr 类型(一种混合类型)的形式出现。 OTOH,当将 CLI 参数限制为 Num 或 Int 时,Perl6 将检查您是否实际将数字放在那里 - 或者至少,unicode 认为数字是什么。
如果您想要实际的文件名,您可以通过强制输入 IO()
来节省验证步骤。那么它只会在你命名一个文件时起作用。最后,将 where .r
放在参数之后将坚持它是可读的:
sub MAIN(IO() $file where .r, *@others) { ...
坚持一个强制性参数的短行,该参数是一个引用可读文件的文件名,具有不同数量的其他参数和一条有用的使用消息,如果它全部出现问题,则会自动生成...