开发者

How can a function return its argument list as an array reference

How would I go about writing a function that returns its a开发者_JS百科rguments as a reference to a array?


sub f {
   return [@_];
}

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

The [@foo] construct creates a reference to a new, anonymous array (copy of @foo), while the \@foo construct creates a reference to the @foo array, whose contents might later change.


There are a few ways to create a subroutine that returns its arguments as an array:

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

There are several important differences between array and 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'

As these examples show, the array produced by array() is copied by value, and those values are independent from the original arguments. The array produced by capture() retains a bi-directional alias to its argument list.

Another difference is in speed. capture() is about 40% faster than array() since it does not have to copy the elements of the array (or even look at them for that matter). This speed difference will of course vary depending on the length of the argument list.

An additional effect of capture() not even touching its elements is that if an argument that would normally allocate memory is used, that allocation will not happen until the argument is touched:

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'

In my own code, I usually spell capture() as cap() or just write it inline:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜