当我偶然发现这个S.O时,我正在寻找一个关于如何使用标量传递数组(或列表)的帖子。发表... Passing By Value - S.O.
我发现选择的答案解决方案有效,但由于我正在尝试学习Perl,我想知道它是如何工作的。在这一行
my($inVal, $inValTwo, $inArray, $inArrayTwo) = @_;
我看到作者将传递给子程序的输入参数放入标量变量中。然后,在这一行
@{$inArray}
他说"使用引用作为数组"。他的意思是什么以及第二行究竟发生了什么?我还没有看到像这样的那些运营商。
答案 0 :(得分:5)
首先要记住的是arrays and lists are not the same。
引用是一个标量,它保存其他内存的地址 - 数组,哈希,另一个标量等。它是一种奇特的指针。
Perl中的子程序获取一个参数列表(并返回一个结果列表。)当你想做类似
之类的事情时,这是一个常见的绊脚石mysub( @foo, @bar )
然后您意识到@foo
和@bar
的元素在您的子例程中被压缩成一个列表。如果你提前知道@foo
的大小,你可以从列表的开头抓取正确数量的元素,但通常你不会。
引用可以解决这个问题,因为它们是标量。如果您将引用传递给@foo
和@bar
,您就知道您的子程序将始终有两个参数需要处理,无论引用数组的大小如何。
但是我们仍然需要获取这些数组中的数据。要做到这一点,我们必须告诉Perl去获取引用指向的东西。这称为解除引用。
在Perl中,有两种常用的方法可以取消引用数组引用:
my @array = @$ref;
my $elem = $ref->[42]
。请注意,第一个示例有时会写为@{ $ref }
,但除非您需要消除某些嵌套结构的歧义,否则不需要额外的curlies。有些人喜欢总是使用额外的曲线,但我发现它们会增加杂乱,通常是不必要的。
有关引用令人兴奋的主题的更多信息,请查看
答案 1 :(得分:2)
在perl中,将标量列表传递给子例程。
标量值可以是:
因此,在调用子例程时,可以传递整个数组(因为数组是标量列表)
my @list = (1, 2, 3);
#note the variable declaration being surrounded by parenthesis.
#that says use list context
sub getList {
my ($foo, $bar, $baz) = @_; #(@_ is the list you passed to the sub)
}
现在,如果您想要传递给子程序的2个列表,则无法执行
getList(@listA, @listB);
因为这两个列表将被展平为@_
中包含的单个数组。
因此,要解决此问题,请使用引用,或将数组作为参考传递。
my $first_list = \@listA #this points $first_list to a reference in
#memory where @listA is located.
getList($first_list, \@listB);
sub getList {
my ($foo, $bar) = @_; #$foo and $bar now point to @listA and @listB
#To dereference these, you either have to use the -> operator to access
#Elements, or use the form @{ }. %{ } for hashes.
my @listA = @{ $foo };
my @listB = @{ $bar };
#Now they are regular arrays again!
}