Ответ 1
В Perl аргументы подпрограммы, хранящиеся в @_
, всегда являются псевдонимами для значений на сайте вызова. Это сглаживание сохраняется только в @_
, если вы скопируете значения, то, что вы получаете, значения.
поэтому в этом суб:
sub example {
# @_ is an alias to the arguments
my ($x, $y, @rest) = @_; # $x $y and @rest contain copies of the values
my $args = \@_; # $args contains a reference to @_ which maintains aliases
}
Обратите внимание, что это псевдонижение происходит после расширения списка, поэтому, если вы передали массив в example
, массив расширяется в контексте списка, а @_
задается псевдонимами каждого элемента массива (но сам массив недоступен для example
). Если вы захотите последнего, вы передадите ссылку на массив.
Слияние аргументов подпрограммы - очень полезная функция, но ее необходимо использовать с осторожностью. Чтобы предотвратить непреднамеренную модификацию внешних переменных, в Perl 6 вы должны указать, что вы хотите записывать аргументы с псевдонимом с помощью is rw
.
Один из менее известных, но полезных трюков - использовать эту функцию псевдонимов для создания массива refs псевдонимов
my ($x, $y) = (1, 2);
my $alias = sub {\@_}->($x, $y);
$$alias[1]++; # $y is now 3
или псевдонимы:
my $slice = sub {\@_}->(@somearray[3 .. 10]);
также выясняется, что использование sub {\@_}->(LIST)
для создания массива из списка на самом деле быстрее, чем [ LIST ]
, поскольку Perl не нужно копировать каждое значение. Конечно, недостаток (или потенциал роста в зависимости от вашей точки зрения) заключается в том, что значения остаются псевдонимами, поэтому вы не можете их изменять без изменения оригиналов.
Как отмечает tchrist в комментарии к другому ответу, когда вы используете любую конструкцию псевдонимов Perl на @_
, $_
, которую они предоставляют вам, также является псевдонимом исходных аргументов подпрограммы. Например:
sub trim {s!^\s+!!, s!\s+$!! for @_} # in place trimming of white space
Наконец, все это поведение является nestable, поэтому при использовании @_
(или его части) в списке аргументов другой подпрограммы он также получает псевдонимы для первых аргументов подпрограммы:
sub add_1 {$_[0] += 1}
sub add_2 {
add_1(@_) for 1 .. 2;
}