我如何编写一个返回其参数作为数组引用的函数?
答案 0 :(得分:12)
sub f {
return [@_];
}
$ref = f(2, 3, 5);
print "@$ref\n";
[@foo]
构造创建对新的匿名数组(@foo
的副本)的引用,而\@foo
构造创建对@foo
数组的引用,内容可能会稍后改变。
答案 1 :(得分: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()
比array()
快约40%,因为它不必复制数组的元素(甚至不需要查看它们)。这种速度差异当然会根据参数列表的长度而变化。
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);