20. Функция MAIN в Perl 6, часть 3

На сегодня осталось рассмотреть возможности для управления поведением именованных аргументов. Возможностей немного, но они есть.

Именованные параметры

Перед тем как начать — вопрос: что должна вывести вот такая программа, если ее запустить без каких-либо параметров?

sub MAIN(:$value) {
    say "value=$value"
}

Ответ может показаться неожиданным:

$ perl6 main-6.pl 
Use of uninitialized value $value of type Any in string context.
Methods .^name, .perl, .gist, or .say can be used to stringify it to something meaningful.
  in sub MAIN at main-6.pl line 1
value=

Вместо примера использования мы получили сообщение об ошибке, которое говорит о том, что функция MAIN была-таки вызвана. То есть именованные аргументы не являются обязательными.

При этом если указать аргумент, отсутствующий в сигнатуре, все работает как надо:

$ perl6 main-6.pl --key=42
Usage:
   main-6.pl [--value=<Any>]

Решение проблемы может быть очень легким: если вы действительно ожидаете параметр, укажите, что он должен быть определен (defined):

sub MAIN(Str:D :$value) {
    say "value=$value"
}

Теперь появляется желанный пример использования:

$ perl6 main-6.pl
Usage:
  main-6.pl [--value=<Str>]

Именованные и позиционные параметры

Для параметров, в том числе и для именованных, возможно указать значение по умолчанию. Например:

sub MAIN($value, :$key = 'default') { 
   say "$key=$value"
}

В этом случае программа, запущенная без именованного параметра, тоже покажет пример использования, а не ошибку:

$ perl6 main-7.pl 
Usage:
    main-7.pl [--key=<Any>] <value>

ОК, но теперь возникает другая проблема. Последняя программа ожидает, что именованный параметр передан до позиционного.

Так работает:

$ perl6 main-7.pl --key=answer 42 
answer=42

А так нет:

$ perl6 main-7.pl 42 --key=answer 
Usage:
 main-7.pl [--key=<Any>] <value>

Чтобы заработало и во втором примере, нужно сообщить об этом через специальную динамическую переменную:

my %*SUB-MAIN-OPTS = :named-anywhere;

sub MAIN($value, :$key = 'default') { 
    say "$key=$value"
}

Довольно многословно, но как есть. Теперь можно передавать именованные параметры в любом месте командной строки.

Обязательное =

Наконец, следует обратить внимание на то, что значения именованных параметров требуют знака равенства и отсутствие пробелов вокруг него. Запись в командной строке --key answer 42 будет расценена как три аргумента.

А если значение не указано, то оно будет истиной:

$ perl6 main-7.pl --key 42
True=42

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

3 thoughts on “20. Функция MAIN в Perl 6, часть 3”

  1. В случае использования обязательного и необязательного именованных параметров есть какое-то готовое решение?
    ——
    multi sub MAIN(
    Str:D :$key,
    Int :$int_key
    ) {
    say «key = $key»;
    say «int_key = $int_key»;
    }
    ——
    Работает ожидаемо:
    c:\>perl6 perl6_test.pl.txt
    Usage:
    perl6_test.pl.txt [—key=] [—int_key=]

    c:\>perl6 perl6_test.pl.txt —key=’aaa’ —int_key=’42’
    Usage:
    perl6_test.pl.txt [—key=] [—int_key=]

    c:\>perl6 perl6_test.pl.txt —key=’aaa’ —int_key=42
    key = ‘aaa’
    int_key = 42

    Но:
    c:\>perl6 perl6_test.pl.txt —key=’aaa’
    key = ‘aaa’
    Use of uninitialized value of type Int in string context.
    Methods .^name, .perl, .gist, or .say can be used to stringify it to something m
    eaningful.
    in sub MAIN at perl6_test.pl.txt line 18
    int_key =

    Т.е. в последнем случае хотелось бы избежать применения if $int_key {say «int_key = $int_key»;}, если это возможно «штатным» образом работы с MAIN.

      1. Не на сто процентов то самое:
        c:\>perl6 perl6_test.pl.txt —key=’aaa’
        key = ‘aaa’
        int_key = 0

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

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Retype the CAPTCHA code from the image
Change the CAPTCHA codeSpeak the CAPTCHA code