Perl vivification вопрос при разыменовании undefined ссылка на массив
Мне сложно понять, почему следующие работы:
my $array_reference;
foreach $element (@{$array_reference}) {
# some code
}
в то время как следующее не работает
my $array_reference;
if (scalar (@{$array_reference}) {
# some code here
}
Я понимаю, что perl приносит в жизнь (автоматически оживляет) ссылку undefined. Но я все еще запутался, как в том, почему последний сегмент кода вызывает FATAL.
Ответы
Ответ 1
Выделение autovivify в контексте lvalue (значение, когда ожидается модифицируемое значение), и foreach создает контекст lvalue.
>perl -E"$$x = 1; say $x;"
SCALAR(0x74b024)
>perl -E"++$$x; say $x;"
SCALAR(0x2eb024)
>perl -E"\$$x; say $x;"
SCALAR(0x30b024)
>perl -E"sub {}->($$x); say $x;"
SCALAR(0x27b03c)
>perl -E"for ($$x) {} say $x;"
SCALAR(0x25b03c)
Последние два создают контекст lvalue, потому что им нужно значение, к которому относятся псевдоним $_[0]
и $_
(соответственно).
Ответ 2
Perl имеет несоответствия в этой области, но в целом код, который может модифицировать структуру, автогенерирует, а код, который этого не сделает, не будет. И если он не автовивит, он пытается разыменовать значение undefined, которое вызывает предупреждение или в use strict "refs"
исключение.
Ответ 3
Я думаю, глядя на perlref, что это ожидаемое поведение:
"Ссылки соответствующего типа могут spring существовать, если вы разыщите их в контексте, который предполагает, что они существуют."
Аналогичная вещь для foreach происходит с push() и друзьями:
my $f;
push @$f, 1;
say @$f;
Хотя не с новыми версиями can-just-take-a-reference:
my $f = [];
push $f, 1;
say @$f;
работает, а
my $f;
push $f, 1;
say @$f;
нет, что, по моему мнению, разумно, поскольку толчок не знает, что вы на самом деле имели в виду.
Интересный вопрос заключается в том, должен ли скаляр (@$undef) делать то же самое или должен предупреждать, поскольку он в конечном итоге возвращает undef, я думаю, что он может сразу предупредить вас.