【问题标题】:How does this example of passing arrays by reference work in Perl?这个通过引用传递数组的例子在 Perl 中是如何工作的?
【发布时间】:2014-03-25 00:30:33
【问题描述】:

当我偶然发现这个 S.O.发帖...Passing By Value - S.O.

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

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

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

@{$inArray}

他说“将引用用作数组”。他的意思是什么?第二行到底发生了什么?我还没有见过这样组合的运算符。

【问题讨论】:

    标签: arrays perl


    【解决方案1】:

    首先要记住的是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]

    请注意,第一个示例有时写为@{ $ref },但不需要额外的花括号,除非您需要消除某些嵌套结构的歧义。有些人喜欢总是使用多余的卷发,但我发现它们会增加混乱并且通常是不必要的。

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

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

    【讨论】:

    • 哦,好的。这非常有用且内容丰富。惊人的答案!我一直很喜欢 Perl 的优美语法,并且总体上越来越喜欢脚本语言。谢谢!
    • +1 用于链接不是列表的数组,我每天都学到新东西!
    【解决方案2】:

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

    标量值可以是:

    1. 原始数据类型,即。字符串、整数、双精度
    2. 对数组的引用。
    3. 对哈希的引用

    所以在调用子程序时,可以传递整个数组(因为数组是标量列表)

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

    【讨论】:

    • 这也是一个非常有用的答案。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2020-03-09
    • 2017-07-18
    • 1970-01-01
    • 2014-10-22
    • 1970-01-01
    • 2015-12-23
    • 1970-01-01
    • 2018-07-28
    相关资源
    最近更新 更多