Как функция может возвращать список своих аргументов в виде ссылки на массив

#perl

#perl

Вопрос:

Как бы мне написать функцию, которая возвращает свои аргументы в виде ссылки на массив?

Ответ №1:

 sub f {
   return [@_];
}

$ref = f(2, 3, 5);
print "@$refn";
  

[@foo] Конструкция создает ссылку на новый анонимный массив (копию @foo ), в то время как @foo конструкция создает ссылку на @foo массив, содержимое которого позже может измениться.

Ответ №2:

Существует несколько способов создать подпрограмму, которая возвращает свои аргументы в виде массива:

 sub array {[@_]}  # returns an array reference that is a copy of its argument

sub array_verbose {  # the same as array(), but spelled out
    my @copy = @_;
    return @copy;
}

sub capture {@_}  # returns a reference to the actual argument array
  

Существует несколько важных различий между array и capture :

 my ($x, $y) = (3, 4);

my $array = array $x, $y;
my $capture = capture $x, $y;

say "@$array, @$capture";  # prints '3 4, 3 4'

$x  ;

say "@$array, @$capture";  # prints '3 4, 4 4'

$$capture[1] *= 2;

say "@$array, @$capture";  # prints '3 4, 4 8'

say "$x $y";  # prints '4 8'
  

Как показывают эти примеры, массив, созданный array() , копируется по значению, и эти значения не зависят от исходных аргументов. Массив, созданный capture() , сохраняет двунаправленный псевдоним для своего списка аргументов.

Другое отличие заключается в скорости. capture() примерно на 40% быстрее, чем array() , поскольку ей не нужно копировать элементы массива (или даже просматривать их, если уж на то пошло). Эта разница в скорости, конечно, будет варьироваться в зависимости от длины списка аргументов.

Дополнительный эффект от того, что capture() даже не прикасаются к его элементам, заключается в том, что если используется аргумент, который обычно выделяет память, это выделение не произойдет, пока аргумент не будет затронут:

 my %hash;
my $hashcap = capture $hash{a}, $hash{b}, $hash{c};

say join ', ' => keys %hash; # prints nothing

$_   for @$hashcap;

say join ', ' => keys %hash; # prints 'c, a, b'
  

В моем собственном коде я обычно пишу capture() как cap() или просто пишу его встроенным:

 my $y = sub{@_}->(map $_**2, 1..10);