Передача массивов в Perl
Я думаю, что неправильно понял некоторые аспекты передачи аргументов в функции Perl. Какая разница между func(\@array)
и func(@array)
?
AFAIK, в обеих функциях аргументы передаются по ссылке, и в обеих функциях мы можем изменить элементы @array
в основной программе. Так какая разница? Когда мы должны использовать, который?
@array = (1,2,3);
func(@array);
func(\@array);
sub func {
...
}
Также, как я могу имитировать pass-by-value в Perl? Использует ли @_
единственный способ?
Ответы
Ответ 1
AFAIK, в обеих функциях аргументы передаются по ссылке, и в обеих функциях мы можем изменять элементы @array в основной программе.
"измените элементы", да. Тем не менее, в случае func(@array)
у sub нет средств для внесения других изменений в массив (усечение его, нажатие, выскакивание, нарезка, передача ссылки на что-то еще, даже отказ от нее).
Я бы избегал использовать термин "пройденный по ссылке", так как механизм полностью отличается от ссылок на Perl. Он менее перегружен:), чтобы сказать, что в sub элементы @_
начинаются с псевдонимов с элементами, переданными в sub.
Ответ 2
Невозможно передать массивы подлогам. Subs принимают список скаляров для аргумента. (И это единственное, что они могут вернуть тоже.)
Вы можете передать ссылку на массив:
func(\@array)
Вы можете передать элементы массива:
func(@array)
Когда мы должны использовать какой?
Если вы хотите передать больше, чем просто элементы массива (например, pass $x
, $y
и @a
), это может стать сложным, если вы не передадите ссылку.
Если вы собираетесь обрабатывать списки (например, sum mysub grep { ... } ...
), вам может не потребоваться передать ссылку.
Если вы хотите изменить массив (в отличие от простого изменения существующих элементов массива), вам необходимо передать ссылку.
Может быть более эффективным передать ссылку для длинных массивов, поскольку создание и размещение одной ссылки в стеке происходит быстрее, чем создание псевдонима для каждого элемента большого массива. Однако это редко будет проблемой.
Обычно это определяется одним из первых двух из вышеперечисленных. Помимо этого, в основном это вопрос личных предпочтений.
Также, как мне подражать pass-by-value в Perl?
sub foo {
my ($x) = @_; # Changing $x doesn't change the argument.
...
}
sub foo {
my @a = @_; # Changing @a or its contents
... # doesn't change the arguments.
}
Ответ 3
func(\@array)
передает ссылку. func(@array)
передает список (элементов в @array
). Как отметил Кит, эти элементы передаются по ссылке. Тем не менее, вы можете сделать копию внутри sub, чтобы пройти по значению.
Зачем вам нужно следующее:
sub func {
my @array = @_;
}
Это передаст копию аргументов func
to @array
, которая является локальной переменной в рамках подпрограммы.
Документация здесь