Вопрос оживления 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, я думаю, что он может также сразу предупредить.

Другие вопросы по тегам