Как потребовать 1 или более аргумента в MAIN - PullRequest
0 голосов
/ 02 мая 2018

Прямо сейчас у меня есть подпрограмма MAIN, которая может принимать один или несколько строковых аргументов. Но я использую два отдельных параметра для MAIN, чтобы сделать это:

sub MAIN (
    Str:D $file,
    *@files,
) {
    @files.prepend: $file;

    # Rest of the program
}

Теперь мне интересно, есть ли более идиоматический способ добиться этого, так как мое текущее решение кажется немного неуклюжим и не слишком перли.

Ответы [ 4 ]

0 голосов
/ 03 мая 2018

С риском «чрезмерного ответа» - мой взгляд на «Перли» лаконичен, насколько это возможно, не становясь неясным (возможно, я просто заменяю один субъективный термин двумя другими ...: -)

Если в качестве единственного параметра используется массив slurpy, он с радостью не примет аргументов, выходящих за пределы спецификации, которую вы указали в комментариях. Тем не менее, позиционный параметр является обязательным по умолчанию, и proto * необходимы только в том случае, если вы хотите исключить ограничения для всех мульти - предположительно, излишнее для того, что вы хотите здесь. Итак, этого достаточно:

sub MAIN($file , *@others) {
    say "Received file, $file, and @others.elems() others."
} 

Это близко к тому, что положил mr_ron - но почему бы не пойти с сообщением об использовании по умолчанию, которое MAIN любезно подбирает для вас, изучив ваши параметры:

$ ./f.pl
Usage:
  ./f.pl <file> [<others> ...]

Кто-то может сказать, что я обманул, отбросив ограничение типа Str на первый параметр, но на самом деле это мало что дает, когда вы ограничиваете строки, потому что числа, указанные в CLI, показываются как тип IntStr (разновидность гибридного типа), которая удовлетворяет ограничению Str. OTOH, ограничивая параметры CLI значениями Num или Int, Perl6 проверит, действительно ли вы вводите цифры - или, по крайней мере, то, что Unicode считает цифрами.

Если вам нужны реальные имена файлов, вы можете сохранить шаг проверки, ограничившись типом IO(). Тогда это будет работать, только если вы назовете файл. И, наконец, установка where .r после параметра будет настаивать на том, что он может быть загружен:

sub MAIN(IO() $file where .r, *@others) { ...

Одна короткая строка, которая настаивает на одном обязательном аргументе, который является именем файла, ссылающимся на читаемый файл, с переменным числом других параметров и полезным автоматически генерируемым сообщением об использовании, если все идет вбок ...

0 голосов
/ 02 мая 2018

Вы также можете попробовать использовать просто динамические переменные:

die "Usage: $*EXECUTABLE <file> <file2>*" if !+@*ARGS;
my @files =  @*ARGS;

где @*ARGS - это массив с аргументами, выданными в командной строке

Вы даже можете использовать @*ARGFILES, поскольку они на самом деле являются файлами

0 голосов
/ 02 мая 2018

Вы можете сделать это с proto sub

proto sub MAIN ( $, *@ ){*}

multi sub MAIN ( *@files ) {
    # Rest of the program
}

или с дополнительной подписью

sub MAIN ( *@files ($,*@) ) {
    # Rest of the program
}
0 голосов
/ 02 мая 2018

Возможно, достаточно хороший ответ здесь:

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

...