为什么undef变量变成没有定义的{}?

时间:2019-09-04 12:27:28

标签: perl

我正在研究Webmin的source code

($wuser) = grep { $_->{'name'} eq $in{'user'} } &acl::list_users();

如果我们像$in{'user'}一样传递?user=notexist,变量$wuser将是undef,不是吗?

抽象代码描述了下面发生的事情。

# $wuser is undef now.
#die Dumper($wuser);
if($wuser){die 'not die here';}
        if ($wuser->{'pass'} eq 'x') {
                #never reach here.
                die 'not die in branch 1';
        }
        elsif ($wuser->{'pass'} eq '*LK*' ||
               $wuser->{'pass'} =~ /^\!/) {
                #never reach here too.
                die 'not die in branch 2';
        }
if($wuser){die 'so....why die here '.Dumper($wuser);}
# $wuser is {} now.
}

所以...什么时候以及如何undef变量变成{}而没有任何定义...

1 个答案:

答案 0 :(得分:8)

这里的问题是Perl功能,称为“自动生存”。基本上,这意味着,如果将未定义的Perl变量视为引用类型,则Perl将创建该类型的引用并将其存储在变量中。

因此,当您执行以下语句时,您的问题就开始了:

if ($wuser->{'pass'} eq 'x')

Perl认为您将$wuser视为哈希引用,因此它将创建一个空哈希并将该哈希的引用存储在$wuser中。然后,它可以在该哈希中查找“ pass”键,并发现它不存在。

通常,这被视为一项功能。您可以运行以下代码:

my $hash; # created as undef
$hash->{foo}{bar}{baz} = 1;

Perl将为您创建此数据结构:

{
  'foo' => {
    'bar' => {
      'baz' => 1
    }
  }
};

您无需费心创建哈希的所有中间级别。

当然,您的代码是人为的。您知道开始寻找密钥时$wuser为假。所有引用都是正确的,因此错误的引用永远不能包含键。