您正在测试数字零的未定义值。当然,你会得到一个真实的结果!你期待什么?
您还应该在use warnings
. 你为什么不呢?
如果您不使用以下方式启动程序:
use v5.12; # or whatever it is you are using
use strict;
use warnings;
你真的不应该打扰。:)
编辑
注意:我只是为了澄清正确性,因为注释行对此不利。我真的不可能不在乎一个关于声誉点的抱怨。我只是想让人们理解。
即使在 CPANautovivification
模块下,也没有任何变化。见证:
use v5.10;
use strict;
use warnings;
no autovivification;
my %md_hash = ();
$md_hash{top}{primary}{secondary} = 0;
if ($md_hash{top}{foobar}{secondary} == 0) {
say "yup, that was zero.";
}
运行时,它说:
$ perl /tmp/demo
Use of uninitialized value in numeric eq (==) at /tmp/demo line 10.
yup, that was zero.
测试是==
操作员。它的 RHS 是0
. 它的 LHSundef
与 autovivification 无关。由于undef
是 数字0
,这意味着 LHS 和 RHS 都包含0
,==
正确识别为持有相同的数字。
自动生存不是这里的问题,正如 ysth 在他写道“这不是一个多维散列特定问题”时正确观察到的那样。重要的是你传递给什么==
。并且undef
在数字上是0
。
如果您真的非常想停止 autoviv,可以使用 CPAN pragma。但是你永远无法通过抑制 autoviv 来改变这里发生的事情。这表明这根本不是自动生存问题,只是一个undef
问题。
现在,当你这样做时,你会得到“额外的”键,因为未定义的左值将在通过解引用链的过程中被填充。这些必然都是一样的:
$md_hash{top}{foobar}{secondary} # implicit arrow for infix deref
$md_hash{top}->{foobar}->{secondary} # explicit arrow for infix deref
${ ${ $md_hash{top} }{foobar} }{secondary} # explicit prefix deref
每当您undef
在 Perl 中取消引用一个左值时,该存储位置总是会填充有对新分配的正确类型的匿名引用的正确类型的引用。简而言之,它 autovivs。
而且您可以通过抑制或回避自动激活来停止。然而,否认 autoviv 与回避它并不相同,因为您只需更改返回的内容类型。整体表现仍然得到充分评估:不会因为您抑制 autoviv 而自动短路。那是因为 autoviv 不是问题(如果它不存在,你会很生气:相信我)。
如果你想短路,你必须自己写。我似乎从来不需要自己。在 Perl 中,就是这样。另一方面,C 程序员非常习惯于编写
if (p && p->whatever) { ... }
因此,如果您愿意,您也可以这样做。但是,在我自己的经验中,这种情况很少见。你几乎不得不在 Perl 中犯错才能有所作为,因为如果有空级别,很容易安排你的代码不改变它的行为方式。