Добавление сигнатур

Сигнатура подпрограммы решает две задачи. Во первых, она объявляет список обязательных и необязательных аргументов, передаваемых при вызове подпрограммы. Во вторых, с помощью сигнатуры объявляются переменные и их связь с аргументами подпрограммы. Эти переменные называются параметрами. Сигнатуры в Perl 6 обладают дополнительными возможностями: они позволяют ограничивать значения аргументов, сравнивать и извлекать сложные структуры данных.

Основы

В своей простой форме сигнатура - список разделенных запятой имен переменных, с которыми связываются входные аргументы подпрограммы.

    sub order-beer($type, $pints) {
        say ($pints == 1 ?? 'A pint' !! "$pints pints") ~ " of $type, please."
    }

    order-beer('Hobgoblin', 1);    # A pint of Hobgoblin, please.
    order-beer('Zlatц+ Baе+ant', 3); # 3 pints of Zlatц+ Baе+ant, please.

Использование термина связываются вместо присваиваются весьма существенно. Переменные в сигнатуре являются ссылками в режиме "чтения" на передаваемые подпрограмме аргументы. Это делает недоступными для модификаций входные значения.

Связывание в режиме "только чтение" можно отменить. Если пометить параметр атрибутом is rw, то передаваемое значение можно будет изменять. Эти изменения будут применены также к оригинальным данным, передаваемым при вызове подпрограммы. В случае, если будет передан литерал или другое константное значение для rw параметра, то связывание завершиться ошибкой в месте вызова подпрограммы, вызвав программное исключение:

    sub make-it-more-so($it is rw) {
        $it ~= substr($it, $it.chars - 1) x 5;
    }

    my $happy = "yay!";
    make-it-more-so($happy);
    say $happy;                # yay!!!!!!
    make-it-more-so("uh-oh");  # Fails; can't modify a constant

Также возможно создание копии передаваемых значений с помощью is copy. В таком случае, данные вне подпрограммы будут защищены от модификаций, а внутри подпрограммы могут быть изменены:

    sub say-it-one-higher($it is copy) {
        $it++;
        say $it;
    }

    my $unanswer = 41;
    say-it-one-higher($unanswer);  # 42
    say-it-one-higher(41);         # 42

Столь подробная маркировка изменяемых параметров может показать чрезмерной, но скорее всего вы не будете использовать эти модификаторы часто. В то время как некоторые языки требуют пометки параметров rw для эмуляции возврата множественных результатов, Perl 6 позволяет напрямую возвращать несколько значений в ответе без подобных фокусов.

Передача массивов, хэшей и кода

Сигил переменной указывает на ее предназначение. В сигнатуре, сигил переменной ограничивает типы передаваемых аргументов. Например, сигил @ определяет проверку передаваемых значений на соответствие типу Positional (Позиционный), который включает в себя типы наподобие Array (массивов) и списков. При передаче параметров нарушающих это ограничение на экран будет выведено сообщение об ошибке.

    sub shout-them(@words) {
        for @words -> $w {
            print uc("$w ");
        }
    }

    my @last_words = <do not want>;
    shout-them(@last_words);  # DO NOT WANT
    shout-them('help');       # Fails; a string is not Positional

Соответственно, сигил % указывает, что ожидается нечто Associative (Ассоциативное), т.е. что-то позволяющее индексирование с помощью операторов <...> или {...}. В свою очередь сигил & требует указания чего-то вызываемого, например анонимной подпрограммы. В таком случае производить вызов этого параметра можно без указания сигила &:

    sub do-it-lots(&it, $how-many-times) {
        for 1..$how-many-times {
            it();
        }
    }

    do-it-lots(sub { say "Eating a stroopwafel" }, 10);

Скаляр (сигил &) не имеет ограничений. Что угодно может быть связано с ним, даже если оно может связываться с другими сигилами.