Вопрос оживления Perl при разыменовании неопределенной ссылки на массив
Мне трудно понять, почему работает следующее:
my $array_reference;
foreach $element (@{$array_reference}) {
# some code
}
пока следующее не работает
my $array_reference;
if (scalar (@{$array_reference}) {
# some code here
}
Я понимаю, что Perl оживляет (автоматически оживляет) неопределенную ссылку. Но я все еще не понимаю, почему последний сегмент кода выбрасывает FATAL.
3 ответа
Разыменовывает autovivify в контексте lvalue (имеется в виду, когда ожидается изменяемое значение) и создает каждый контекст 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]
а также $_
(соответственно).
В Perl есть несоответствия в этой области, но в целом код, который может изменить структуру, автоматически активируется, в то время как код, который этого не делает. И если он не автовифицируется, он пытается разыменовать неопределенное значение, которое вызывает предупреждение, или, под use strict "refs"
, исключение.
Я думаю, глядя на perlref, что это ожидаемое поведение:
"Ссылки соответствующего типа могут возникать, если вы разыменовываете их в контексте, который предполагает, что они существуют".
Аналогичная вещь для foreach происходит с push() и friends:
my $f;
push @$f, 1;
say @$f;
Хотя и не с новыми версиями, которые можно просто взять с собой:
my $f = [];
push $f, 1;
say @$f;
работает, пока
my $f;
push $f, 1;
say @$f;
нет, что я считаю разумным, так как толчок не знает, что вы на самом деле имели в виду.
Интересный вопрос заключается в том, должен ли скаляр (@$undef) делать то же самое или должен предупреждать, так как он в конечном итоге возвращает undef, я думаю, что он может также сразу предупредить.