我的Perl代码类似于以下内容:
# -- start --
my $res;
# run query to fetch IPv6 resources
while( my $row = $org_ip6_res->fetchrow_arrayref )
{
if( $row->[4] =~ /PA/ ) {
$res->{ipv6}{pa}{$row->[2]}++;
} elsif( $row->[4] eq 'PI' ) {
$res->{ipv6}{pi}{$row->[2]}++;
}
}
# -- stop --
在迭代查询结果之前,$res
始终没有设置,但代码运行得很好。
当我在每个值之前放置print语句时,我在两种情况下都会出现空白,但如果在应用了增量之后出现了print语句,我会得到一个值> = 1,具体取决于组织拥有多少IPv6资源。
我的问题是,我是否认为这意味着Perl中未初始化的哈希键自动具有零值?
很抱歉,如果它是一个新手问题,但我只是不熟悉这样的结构
即$hashref->{foo}->{bar}++
其中值尚未明确分配给$hashref->{foo}->{bar}
。提前谢谢!
答案 0 :(得分:26)
该值不会自动为零。该值最初未定义。但是,如果您将其视为数字(例如,将++
应用于它),则Perl会将其视为零。如果你将它视为一个字符串(例如,将.
应用于它),那么Perl将其视为空字符串。
来自perldoc perlsyn
,在'声明'下:
您需要申报的唯一内容 Perl是报告格式和 子程序(有时甚至不是 子程序)。变量持有 未定义的值(“undef”),直到它有 被分配了一个定义的值,其中 除了“undef”之外的任何东西。什么时候 用作数字,“undef”被处理 为0;当用作字符串时,它是 被视为空字符串,“”;和 当用作参考时不是 被分配给它,它被视为一个 错误。
答案 1 :(得分:5)
详细说明Telemachus的帖子,未初始化的值将是未定义的。结构的深部是autovivified。这是一个方便的功能,可以自动为您创建数据结构。当你想要它时,自动复原很棒,但是当你想要防止它时它会很痛苦。在了解自动生成的过程中,网上有很多教程,文章和帖子。
因此,如果给定未定义的$ref
和$ref->{ipv6}{pa}{'foo'}++
,$ref
将被赋值为:
$ref = {
ipv6 => {
pa => {
foo => undef
}
}
};
然后undef将递增,因为undef编号为0,我们得到0 ++,即1。
最终结果为:ref->{ipv6}{pa}{'foo'} == 1
。
如果您启用了警告,(您执行use warnings;
,不是吗?)当您操作这些未定义的值时,您将收到“未初始化的值”警告。如果是增加酉值的理想行为,那么您可以在代码的有限部分内关闭所需的警告组:
use strict;
use warnings;
my $res;
// run query to fetch IPv6 resources
while( my $row = $org_ip6_res->fetchrow_arrayref )
{ no warnings 'uninitialized';
if( $row->[4] =~ /PA/ ) {
$res->{ipv6}{pa}{$row->[2]}++;
} elsif( $row->[4] eq 'PI' ) {
$res->{ipv6}{pi}{$row->[2]}++;
}
}
您可以在perllexwarn中找到警告层次结构。
答案 2 :(得分:4)
它基本上是未定义的,但当你递增时它被视为零。
Perl用语中的术语是'autovivified'。
您可能想要做的是使用exists keyword:
$res->{ipv6}{pa}{$row->[2]}++ if exists($res->{ipv6}{pa}{$row->[2]});
答案 3 :(得分:2)
没有未初始化的哈希键。可以未初始化的是特定键的值。哈希值只是一个标量值;它与$foo
之类的变量没什么区别。
在您的示例中,有几个不同的Perl功能进行交互。
最初$res
未定义(即它具有值undef
)。当您使用未初始化的值作为哈希引用时(如在$res->{ipv6}...
中),Perl“将其自动”为一个。也就是说,Perl创建一个匿名哈希,并将undef
的值替换为对新哈希的引用。每次使用结果值作为参考时,此过程都会重复(静默)。
最后,您自动生成$res->{ipv6}{pa}{$row->[2]}
的方式,这是未定义的。请记住,这只是像$foo
这样的标量值。行为与说
my $foo;
$foo++;
当您使用未定义的值时,Perl会执行特殊操作。如果将它们用作数字,Perl会将它们转换为0.如果将它们用作字符串,Perl会将它们转换为''(空字符串)。在大多数情况下,如果您启用了警告(您应该这样做),您将获得“使用未初始化的值...”警告。但auto-increment运算符(++
)是一个特殊情况。为方便起见,它会在递增之前将值从undef
静默转换为0
。