【问题标题】:Inconsistent behavior concerning "Can't use an undefined value as an ARRAY reference"关于“不能使用未定义的值作为数组引用”的不一致行为
【发布时间】:2016-01-07 07:18:03
【问题描述】:

为什么会出现以下代码:

use strict;
use warnings;
no warnings 'uninitialized';

use Data::Dumper;

my $user;
my @data = @{$user->{ENTERPRISE}}; # Error on this line
print Dumper($user), qq{Done!\n};

抛出错误“Can't use an undefined value as an ARRAY reference”,而下面的代码:

use strict;
use warnings;
no warnings 'uninitialized';

use Data::Dumper;

my $user;
foreach my $enterprise(@{$user->{ENTERPRISES}}) {
    print qq{Enterprise:}, $enterprise;
}
print Dumper($user), qq{Done!\n};

不抛出任何东西,而是返回:

$VAR1 = {
          'ENTERPRISES' => []
        };
Done!

两者都有违规代码,但只有一个抛出错误。

可能的答案: Perl's autovivification?

我在正确的轨道上吗?感谢您的意见。

【问题讨论】:

  • 你到底想做什么?您已关闭警告以执行此操作这一事实应该是一个非常好的警告,这不是一个好主意。
  • 我只是想弄清楚 Perl 是如何将错误抛出到一个地方而不是另一个地方的相同代码位。第一个代码块来自抛出错误并且必须修复的旧代码,而第二个代码块是更新的代码,我担心也需要修复,但我想不需要,因为它没有抛出我看到的错误过去。

标签: perl perl5.16


【解决方案1】:

是的,在第二种情况下发生的事情称为自动生存,它只在第二种情况下发生,因为自动生存只发生在左值[1]

所以

@{ $x } = $y;

意思

@{ $x //= [] } = $y;

但是

$y = @{ $x };

不代表

$y = @{ $x //= [] };

请记住,foreach 将其循环变量别名为其迭代的列表中的每个元素,因此这些元素被评估为左值。

自动激活记录在 perlref 中,您可以通过 autovivification pragma 控制自动激活。


  1. 如果最后的引用后跟一个索引(例如->[]->{}),即使索引的整体不是,引用表达式本身也会被评估为左值。这意味着$y = $x->[0];$y = ${ $x }[0]; 可以自动激活$x,即使$y = @{ $x }; 不会。

【讨论】:

  • 这是非常有用的。您关于 foreach 如何通过别名循环变量导致我们处于左值情况的最后一点确实使事情变得清晰。左值/右值的区别是否正式记录在某处?
  • @Morrowind789 在perldoc perlref 在“使用引用”下的第 3 点中简要提及。也在perlglossary中对自动存活的定义。
  • autovivication 的文档(perlref)确实:“这是我们前面提到的一种情况,在这种情况下,引用可能会在左值上下文中出现。[...] 这个过程被称为自动复活。”
  • 另外,您可以通过在脚本中添加no autovivification qw(store) 来防止这种行为。
  • "它只发生在第二种情况下,因为它只发生在左值上。"右值也会发生这种情况,但strict 'refs' 不允许,对吗? perl -E'$a = $b->{c}; say ref($b)'
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多