Вопрос оживления Perl при разыменовании неопределенной ссылки на массив - PullRequest
16 голосов
/ 21 июня 2011

Мне трудно понять, почему работает следующее:

my $array_reference;
foreach $element (@{$array_reference}) {
# some code
}

пока не работает

my $array_reference;
if (scalar (@{$array_reference}) {
    # some code here
}

Я понимаю, что Perl оживляет (автоматически оживляет) неопределенную ссылку. Но я все еще в замешательстве, потому что последний сегмент кода вызывает FATAL.

Ответы [ 3 ]

11 голосов
/ 21 июня 2011

Разыменовывает 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] и $_ (соответственно).

7 голосов
/ 21 июня 2011

В Perl есть несоответствия в этой области, но в целом код, который может изменить структуру, автоматически оживляет, а код, который этого не делает. И если он не выполняет автовивификацию, он пытается разыменовать неопределенное значение, что вызывает предупреждение или, при use strict "refs", исключение.

4 голосов
/ 21 июня 2011

Я думаю, глядя на perlref , что это ожидаемое поведение:

" Ссылки соответствующего типа могут возникать, если вы разыменовываете их в контексте, который предполагаетони существуют."

То же, что и в foreach, происходит с push () и друзьями:

my $f;
push @$f, 1;
say @$f;

Хотя не с новым, можно просто взять ссылкуверсии:

my $f = [];
push $f, 1;
say @$f;

работает, в то время как

my $f;
push $f, 1;
say @$f;

нет, что я считаю разумным, так как push не знает, что вы на самом деле имели в виду.

ИнтересноеВопрос в том, должен ли скаляр (@ $ undef) делать то же самое или должен предупреждать, так как он в конечном итоге возвращает undef, я думаю, что он может также сразу предупредить.

...