修改子例程参数(Perl)

修改子例程参数(Perl),perl,parameters,subroutine,Perl,Parameters,Subroutine,我想编写一个Perl子例程first,它将列表作为输入,返回列表中的第一个元素,并从列表中删除第一个元素 像这样: @list = (1,2,3); print first(@list); // 1 print @list; // 23 这不太管用: sub first(@) { return shift @_; } 我得到的是: print first(@list); // 1 print @list; // 123 堆栈变量@改变了我期望的方式(首先是(1,2,3),然后是(2

我想编写一个Perl子例程
first
,它将列表作为输入,返回列表中的第一个元素,并从列表中删除第一个元素

像这样:

@list = (1,2,3);
print first(@list); // 1
print @list; // 23
这不太管用:

sub first(@) {
    return shift @_;
}
我得到的是:

print first(@list); // 1
print @list; // 123
堆栈变量@改变了我期望的方式(首先是
(1,2,3)
,然后是
(2,3)
),但是我作为输入给出的列表(
@list
)没有改变。我认为stack变量保存了对它引用的变量的引用

当我更改子例程中的列表元素时,它也会更改
@list
中的某些内容,但不是我想要更改的,而是+1。如果我在子程序中写:

@_[0] = "X";

在执行子例程print
@list
之后,我会得到
2X6

您需要在
@
原型前面放一条斜线以获得数组引用,然后修改引用。如果只使用
@
,您将在子例程中获得数组
@列表
的副本(因此不会修改父级中的数组)。发件人:

无背景斜杠原型字符具有特殊含义。任何 unbackslashed@或%将吃掉所有剩余的参数,并强制列表 上下文

所以你可以写:

use strict;
use warnings;

sub first (\@) {
    my $a = shift;
    return shift @$a;
}

my @list = (1,2,3);
print first(@list) . "\n"; 
print "@list" . "\n"; 
输出:

1
2 3

这里没有列表,只有数组。数组和列表在Perl中是不同的(正如本文所解释的)。如果您有一个名为
@list
的数组,那么肯定会让您自己(以及将来维护您的代码的人)感到困惑。

为什么不使用
shift
来实现这一点呢?这就是我在子例程中所做的事情,但您为什么要编写子例程呢?什么时候可以简单地使用
shift