Как функция может вернуть свой список аргументов в виде ссылки на массив - PullRequest
0 голосов
/ 12 января 2011

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

Ответы [ 2 ]

12 голосов
/ 12 января 2011
sub f {
   return [@_];
}

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

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

2 голосов
/ 12 января 2011

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

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); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...