Perl 不一致的行为涉及;Can';t使用未定义的值作为数组引用";

Perl 不一致的行为涉及;Can';t使用未定义的值作为数组引用";,perl,perl5.16,Perl,Perl5.16,为什么会出现以下代码: 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}; use strict; use warnings; no warnings 'uninitialized'; use

为什么会出现以下代码:

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};
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};
抛出错误“
不能将未定义的值用作数组引用”
,而以下代码:

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};
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!
两者都有令人不快的代码,但只有一个抛出了错误

可能的答案:


我走对了吗?感谢您的输入。

是的,在第二种情况下发生的情况称为自动活体化,并且只在第二种情况下发生,因为自动活体化只对左值发生[1]

所以

意味着

但是

这并不意味着

$y = @{ $x //= [] };
请记住,foreach将其循环变量别名为它迭代的列表中的每个元素,因此这些元素将作为左值进行计算

自动活体记录在中,您可以通过pragma控制自动活体


  • 如果最后的延迟之后是索引(例如
    ->[]
    ->{}
    ),则引用表达式本身将作为左值进行计算,即使索引的整体不是左值。这意味着
    $y=$x->[0]
    $y=${$x}[0]
    可以自动激活
    $x
    ,即使
    $y=@{$x}不会

  • 你到底想做什么?事实上,您已经关闭了警告,这应该是一个很好的警告,说明这不是一个好主意。第一个代码块来自抛出错误的旧代码,必须修复,而第二个代码块是我担心也需要修复的新代码,但我想不会,因为它没有抛出我在过去看到的错误。这是非常有用的。关于foreach如何工作的最后一点是,通过对循环变量进行别名,使我们处于左值状态,这确实澄清了问题。左值/右值的区别是否有正式记录在案?@Morrowind789在第3点“使用引用”下简要提到了它。同样根据中的自活定义。自活文档(in)中有:“这是我们前面提到的一种情况,在左值上下文中引用可能会出现。[…]此过程称为自活。”此外,您可以通过添加
    无自活qw(存储)来防止这种行为
    到您的脚本。“它只发生在第二种情况下,因为它只发生在左值上。”它也发生在右值上,但被
    严格的“refs”禁止,对吗<代码>perl-E'$a=$b->{c};说ref($b)
    $y = @{ $x //= [] };