Передача массивов в функции в Perl - PullRequest
15 голосов
/ 30 августа 2011

Я думаю, что неправильно понял некоторые аспекты передачи аргументов в функции в Perl.В чем разница между func(\@array) и func(@array)?

AFAIK, в обеих функциях аргументы передаются по ссылке, и в обеих функциях мы можем изменять элементы @array в основной программе.Так в чем же разница?Когда мы должны использовать какие?

@array = (1,2,3);
func(@array);
func(\@array);

sub func {
    ...
}

Кроме того, как мне имитировать передачу по значению в Perl?Является ли использование @_ единственным способом?

Ответы [ 3 ]

20 голосов
/ 30 августа 2011

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

Вы можете передать ссылку на массив:

func(\@array)

Вы можете передать элементы массива:

func(@array)

Когда мы должны использовать какие?

Если вы хотите передать больше, чем просто элементы массива (например, pass $x, $y и @a), он можетстановиться хитрым, если вы не передадите ссылку.

Если вы собираетесь обрабатывать списки (например, sum mysub grep { ... } ...), вы можете не захотеть передавать ссылку.

Если вы хотите изменитьмассив (в отличие от простого изменения существующих элементов массива), вам нужно передать ссылку.

Может быть более эффективно передать ссылку для длинных массивов, поскольку создается и помещается одна ссылка в стекбыстрее, чем создание псевдонима для каждого элемента большого массива.Это редко будет проблемой, однако.

Это обычно решается одним из первых двух из вышеперечисленных.Кроме того, это в основном вопрос личных предпочтений.


Кроме того, как мне имитировать передачу по значению в 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.
}
13 голосов
/ 30 августа 2011

AFAIK, в обеих функциях аргументы передаются по ссылке, и в обеих функциях мы можем изменять элементы @array в основной программе.

"изменить элементы", да. Однако в случае func(@array) подпрограмма не имеет средств для внесения других изменений в массив (усечение, нажатие, выталкивание, разрезание, передача ссылки на что-то еще, даже отмена определения).

Я бы не использовал термин «переданный по ссылке», поскольку механизм полностью отличается от ссылок Perl. Менее перегружен :), чтобы сказать, что в подпрограмме элементы @_ начинаются с псевдонимов к элементам, переданным подпрограмме.

4 голосов
/ 30 августа 2011

func(\@array) передает ссылку.func(@array) передает список (элементов в @array).Как указал Кит, эти элементы передаются по ссылке.Тем не менее, вы можете сделать копию внутри подпрограммы для передачи по значению.

Что вы после этого:

sub func {
    my @array = @_;
}

Это передаст копию аргументов func to @array, которая является локальной переменной в области действия подпрограммы.

Документация здесь

...