shift
将数组的第一个值移开并返回...
这样做是为了速度优化并避免按值复制。
同样在perlsub
数组@_是一个本地数组,但其元素是实际标量参数的别名。特别是,如果更新元素$ _ [0],则更新相应的参数
因此,如果我们在sub中执行my $self = shift
,我们会将第一个值从@_
移位,这是一个别名,不是吗?
但是当我们比较这两个时:
sub test {
print \$_[0]; # SCALAR(0xf73c38)
my $x = shift;
print \$x; # SCALAR(0xf79800)
}
我们看到$x
是副本。
为什么来自@_的shift
ed值不是别名?
因此,如果为案例my $x = shift
复制了值,那么它对my $x = $_[0]
提供了哪些好处?
答案 0 :(得分:9)
移位的值是别名
$ perl -E 'sub F{say \$_[0]; say \shift} $x=42; say \$x; F($x)'
SCALAR(0x1d7f1e0)
SCALAR(0x1d7f1e0)
SCALAR(0x1d7f1e0)
分配操作(例如$x = $_[0]
或$x = shift
)会在右侧创建标量的副本,因此新分配的值不再是别名。
正如工具所说,shift
的好处是修改@_
,这有时会使你在子程序的其余部分中更容易使用。
如果您仍希望能够修改输入
,仍然可以使用引用来移位值$ perl -E 'sub G { my $x=\shift; $$x = 19 } my $z = 42; G($z); say $z'
19
答案 1 :(得分:3)
shift
不是左值运算符。
$ perl -e'
use feature qw( say );
sub f { shift = 456; }
{ my $x = 123; f($x); say $x; }
'
Can't modify shift in scalar assignment at -e line 3, near "456;"
Execution of -e aborted due to compilation errors.
但是,从@_
转移的值仍然是别名。
$ perl -e'
use feature qw( say );
sub f { my $p = \shift; $$p = 456; }
{ my $x = 123; f($x); say $x; }
'
456
或
$ perl -e'
use feature qw( say );
sub f { ${ \shift } = 456; }
{ my $x = 123; f($x); say $x; }
'
456
问题是你将别名数组元素的值赋给$x
而不是将$x
别名化为数组元素。如果要命名@_
的元素,则需要为其添加变量。
$ perl -e'
use feature qw( say );
sub f { our $x; local *x = \shift; $x = 456; }
{ my $x = 123; f($x); say $x; }
'
456
或
$ perl -e'
use feature qw( say );
use Data::Alias qw( alias );
sub f { alias my $x = shift; $x = 456; }
{ my $x = 123; f($x); say $x; }
'
456
或
$ perl -e'
use feature qw( say refaliasing );
no warnings qw( experimental::refaliasing );
sub f { \my $x = \shift; $x = 456; }
{ my $x = 123; f($x); say $x; }
'
456
my $x = shift
优于my $x = $_[0];
的好处很多,虽然很小。
shift
比$_[0]
更容易输入。shift
而不是保持计数。shift
支持复杂和开放式参数列表。 (例如sub f { my $cb = shift; $cb->($_) for @_; }
)shift
在显微镜下比$_[0]
(IIRC)更快。