这个通过引用传递数组的例子如何在Perl中工作?

时间:2014-03-25 00:30:33

标签: arrays perl

当我偶然发现这个S.O时,我正在寻找一个关于如何使用标量传递数组(或列表)的帖子。发表... Passing By Value - S.O.

我发现选择的答案解决方案有效,但由于我正在尝试学习Perl,我想知道它是如何工作的。在这一行

my($inVal, $inValTwo, $inArray, $inArrayTwo) = @_;

我看到作者将传递给子程序的输入参数放入标量变量中。然后,在这一行

@{$inArray}
他说"使用引用作为数组"。他的意思是什么以及第二行究竟发生了什么?我还没有看到像这样的那些运营商。

2 个答案:

答案 0 :(得分:5)

首先要记住的是arrays and lists are not the same

引用是一个标量,它保存其他内存的地址 - 数组,哈希,另一个标量等。它是一种奇特的指针。

Perl中的子程序获取一个参数列表(并返回一个结果列表。)当你想做类似

之类的事情时,这是一个常见的绊脚石
mysub( @foo, @bar )

然后您意识到@foo@bar的元素在您的子例程中被压缩成一个列表。如果你提前知道@foo的大小,你可以从列表的开头抓取正确数量的元素,但通常你不会。

引用可以解决这个问题,因为它们是标量。如果您将引用传递给@foo@bar,您就知道您的子程序将始终有两个参数需要处理,无论引用数组的大小如何。

但是我们仍然需要获取这些数组中的数据。要做到这一点,我们必须告诉Perl去获取引用指向的东西。这称为解除引用。

在Perl中,有两种常用的方法可以取消引用数组引用:

  1. 要获取整个数组,请使用my @array = @$ref;
  2. 要获取数组中的元素,请使用my $elem = $ref->[42]
  3. 请注意,第一个示例有时会写为@{ $ref },但除非您需要消除某些嵌套结构的歧义,否则不需要额外的curlies。有些人喜欢总是使用额外的曲线,但我发现它们会增加杂乱,通常是不必要的。

    有关引用令人兴奋的主题的更多信息,请查看

    1. Perl reference tutorial
    2. Perl reference reference
    3. Perl data structures cookbook

答案 1 :(得分:2)

在perl中,将标量列表传递给子例程。

标量值可以是:

  1. 原始数据类型即。 String,Int,double
  2. 对数组的引用。
  3. 对哈希的引用
  4. 因此,在调用子例程时,可以传递整个数组(因为数组是标量列表)

    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!
    }