为什么从@_ 转移的值不是别名?
Why shifted value from @_ is not alias?
shift
Shifts the first value of the array off and returns it...
这样做是为了优化速度并避免按值复制。
也在perlsub
The array @_ is a local array, but its elements are aliases for the actual scalar parameters. In particular, if an element $_[0] is updated, the corresponding argument is updated
因此,如果我们在 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]
有什么好处?
移位后的值是一个别名
$ perl -E 'sub F{say $_[0]; say \shift} $x=42; say $x; F($x)'
SCALAR(0x1d7f1e0)
SCALAR(0x1d7f1e0)
SCALAR(0x1d7f1e0)
赋值操作(例如,$x = $_[0]
或$x = shift
)在右侧创建标量的副本,因此新赋值不再是别名。
正如 toolic 所说,shift
的好处是修改了 @_
,这有时会使您在子程序的其余部分更容易使用。
如果您仍然希望能够修改输入
,您仍然可以使用对移位值的引用
$ perl -E 'sub G { my $x=\shift; $$x = 19 } my $z = 42; G($z); say $z'
19
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) 快。
shift
Shifts the first value of the array off and returns it...
这样做是为了优化速度并避免按值复制。
也在perlsub
The array @_ is a local array, but its elements are aliases for the actual scalar parameters. In particular, if an element $_[0] is updated, the corresponding argument is updated
因此,如果我们在 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]
有什么好处?
移位后的值是一个别名
$ perl -E 'sub F{say $_[0]; say \shift} $x=42; say $x; F($x)'
SCALAR(0x1d7f1e0)
SCALAR(0x1d7f1e0)
SCALAR(0x1d7f1e0)
赋值操作(例如,$x = $_[0]
或$x = shift
)在右侧创建标量的副本,因此新赋值不再是别名。
正如 toolic 所说,shift
的好处是修改了 @_
,这有时会使您在子程序的其余部分更容易使用。
如果您仍然希望能够修改输入
,您仍然可以使用对移位值的引用$ perl -E 'sub G { my $x=\shift; $$x = 19 } my $z = 42; G($z); say $z'
19
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) 快。