Perl中作为子例程参数的数组和变量

Perl中作为子例程参数的数组和变量,perl,Perl,考虑: sub abc() { } abc(@array, $a); 如何访问子例程abc()中的@array和$a 我知道$\u0]和$\u1],但我不确定是否可以将其用于数组。您可以使用@数组访问sub的参数。第一个参数是$\[0],第二个参数是$\[1],等等。在这种特殊情况下,数组将展开为其元素列表,因此$\[0]是$array[0],$\[1]是$array[1],然后在所有这些元素之后,@的最后一个元素将是$a的值 如果要避免在列表上下文中使用数组时经常发生的展开,请改用对数组

考虑:

sub abc()
{

}

abc(@array, $a);
如何访问子例程abc()中的
@array
$a


我知道
$\u0]
$\u1]
,但我不确定是否可以将其用于数组。

您可以使用
@
数组访问sub的参数。第一个参数是
$\[0]
,第二个参数是
$\[1]
,等等。在这种特殊情况下,数组将展开为其元素列表,因此
$\[0]
$array[0]
$\[1]
$array[1]
,然后在所有这些元素之后,
@
的最后一个元素将是
$a
的值

如果要避免在列表上下文中使用数组时经常发生的展开,请改用对数组的引用。对数组和哈希的引用是使用
\
创建的。因此,调用函数如下:

abc(\@array, $a);

之后,
$\u0]
将引用
@array
$\u1]
将是
$a
。要通过引用访问数组元素,请使用
->
运算符<代码>$\[0]->[2]与
$array[2]
相同。实际上,你甚至可以把
->
放在括号中,这样
$[0][2]
也可以用。请参阅中有关引用的更多详细信息。

如果您传递的是数组引用,而不是Oleg V.Volkov like提到的数组,那就太好了

sub abc()
{
    my ( $array, $a ) = @_; #receiving the paramters
    my @arr = @{$array}; # dereferencing the array
}

abc(\@array,$a);
您有两个选择:

  • 首先传递标量变量(脏方式)

    然后接收子程序中的参数作为

    my ($a, @array) = @_;
    
    my ($array_ref, $a) = @_;
    
  • 通过在数组变量前添加反斜杠将数组作为引用传递(推荐)

    然后接收子程序中的参数作为

    my ($a, @array) = @_;
    
    my ($array_ref, $a) = @_;
    
    并取消对$array\u ref的引用

    my @array = @$array_ref;
    

  • 更多信息。

    其他答案解释了两种基本方法。但是,需要注意的是,这两者之间有很大的区别:当通过引用传递数组时,对其所做的任何更改都会更改原始数组。以下是一个例子:

    use warnings;
    use strict;
    
    my @array = (1, 2, 3, 4, 5);
    
    sub by_ref
    {
        my $array_ref = $_[0];
        @$array_ref = (0, 0, 0);
        print "Array inside by_ref: @$array_ref\n";
    }
    
    sub by_val
    {
        my @array_copy = @_;
        @array_copy = (0,0,0);
        print "Array inside by_val: @array_copy\n";
    }
    
    by_val(@array);
    
    print "Original array after calling by_val: @array\n";
    
    by_ref(\@array);
    
    print "Original array after calling by_ref: @array\n";
    

    如果您确实通过引用传递,则需要记住此行为,如果您不希望sub中所做的更改影响原始数组,请复制引用数组。

    谢谢@Oleg V.Volkov。你能详细说明数组的引用吗?如果你那样做的话,我会给你的。
    我会给你的。
    我知道你在那里做了什么。依我看,第一条路并不肮脏。是的,我同意它有不同的语义。我之所以说dirty,是因为如果要传递的不是scalar,而是第三个变量,那么它将导致其他结果。第一个方法由各种内置函数使用(
    join
    sprintf
    )。只要它适合你所做的,就没有什么问题。我建议我在这里写下:@Zaid,实际上原型是一个严重的错误。此代码不会运行,因为现在
    abc
    不接受任何参数。dan1111是正确的…我只是在运行此代码时遇到了这个问题。您可以在不引用的情况下轻松更改。Try:
    子更改{$\u1]=42};my@arr=(1,2,3);变化(@arr);打印$arr[1],“\n”@OlegV.Volkov,是的,这是一个很好的观点。然而,我认为两者之间的区别仍然很重要。通常的惯例是将传递的参数从
    @
    复制到词法变量中,但使用pass by reference不会阻止您修改原始数组。如果需要在原始数组中反映这些更改,我必须做什么。如果答案太大,请将其作为另一个答案发布…谢谢dan1111。@Daanish使用“按引用传递”,如上面的子
    by_ref
    所示,将更改原始数组。或者,您可以直接修改
    @
    ,正如Oleg V.Volkov在其评论中所示。