解除引用未定义的数组引用时的Perl vivification问题

时间:2011-06-21 02:08:41

标签: perl autovivification

我很难理解为什么以下有效:

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

虽然以下不起作用

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

我理解perl带来生命(自动生存)未定义的引用。但我仍然感到困惑的是为什么后一个代码段会引发致命。

3 个答案:

答案 0 :(得分:11)

在左值上下文中取消引用autovivify(意味着在需要可修改的值时),并且foreach创建左值上下文。

>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)

最后两个创建左值上下文,因为它们需要一个值,分别为$_[0]$_

答案 1 :(得分:7)

Perl在这个领域存在不一致,但一般来说,可能修改结构的代码会自动生成,而代码则不会自动生成。如果它没有自动生成,它会尝试取消引用未定义的值,从而触发警告,或者在use strict "refs"下取消异常。

答案 2 :(得分:4)

我认为,看perlref,这是预期的行为:

如果你在假定它们存在的上下文中取消引用它们,那么适当类型的引用就会存在。

与push()和朋友发生类似的事情:

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

虽然没有新的,可以采取参考的版本:

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

有效,而

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

没有,我认为这是明智的,因为推动不知道你在那里真正意味着什么。

有趣的问题是标量(@ $ undef)应该做同样的事情,还是应该警告,因为它最终会返回undef,我认为它可能会立即发出警告。