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);
精彩评论