Почему смещенное значение из @_ не является псевдонимом? - PullRequest
0 голосов
/ 23 мая 2018

shift
Смещает первое значение массива и возвращает его ...

Это сделано для скоростиоптимизация и избежать копирования по значению.

Также в perlsub

Массив @_ является локальным массивом, но его элементыявляются псевдонимами для фактических скалярных параметров.В частности, если обновляется элемент $ _ [0], обновляется соответствующий аргумент

Таким образом, если мы сделаем 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]?

Ответы [ 2 ]

0 голосов
/ 26 мая 2018

shift не является оператором lvalue.

$ 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).
0 голосов
/ 23 мая 2018

Смещенное значение является псевдонимом

$ 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
...