Вчера мы говорили об обратном слеше, который связывает парметры функции с данными, переданными при вызове. Сегодня мы продолжаем тему и поговорим о тех модификаторах (trait), которыми могут быть снабжены параметры.
Начнем с простого кода:
sub f($x) {
$x++;
say $x;
}
my $v = 42;
f($v);
say $v;
Этот код вполне бы работал в Perl 5.20 (если добавить use feature 'signatures'), но в Perl 6 он завершается с ошибкой:
Cannot resolve caller postfix:<++>(Int); the following candidates
match the type but require mutable arguments:
(Mu:D $a is rw)
(Int:D $a is rw)
The following do not match for other reasons:
(Bool:D $a is rw)
(Bool:U $a is rw --> Bool::False)
(Mu:U $a is rw)
(Num:D $a is rw)
(Num:U $a is rw)
(int $a is rw)
(num $a is rw --> num)
in sub f at args-1.pl line 2
in block at args-1.pl line 7
Сообщение об ошибке большое, но не сообщает о главном: по умолчанию аргументы функции разрешены только для чтения. Если убрать инкремент $x++, то все заработает:
42 42
Параметры в сигнатуре функции могут содержать дополнительные пометки со словом is. Если пометки нет, это все равно что есть is readonly, и, конечно же, понятно, что такую переменную изменить нельзя:
sub f($x is readonly) {
# $x++;
say $x;
}
Хотите что-то менять — передавайте копию переменной (is copy) или разрешайте ее изменять явно (is rw).
sub f($x is copy) {
$x++;
say $x;
}
sub g($x is rw) {
$x++;
say $x;
}
my $v = 42;
f($v); # 43
say $v; # 42
g($v); # 43
say $v; # 43
Понятно, что если передать константу, то изменить ее не получится:
f(42); # 43 g(42); # ошибка
Ошибка сообщает о том, что функция получила целое значение вместо изменяемой переменной (вполне себе сочетаемые слова).
Parameter '$x' expected a writable container, but got Int value
in sub g at args-1.pl line 6
in block at args-1.pl line 19
Наконец, атрибут is raw это то же что и \, но только при этом переменные не лишаются сигила:
sub h($x is raw) {
$x++;
say $x;
}
my $n = 42;
h($n); # 43
say $n; # 43
# h(42); # ошибка
Как видите, возможностей весьма много, но это лишь часть того, на что способны сигнатуры функций в Perl 6.