简体   繁体   English

为什么我的哈希不是undef?

[英]Why is my hash not undef?

I have the following (idealised from a bug) short script in Perl: 我在Perl中有以下简短的脚本(从错误中得到了启发):

my %metadata = undef;
if (defined %metadata)
{
    print "defined";
}

For some reason the output of the program is always "defined". 由于某种原因,程序的输出始终是“定义的”。 So setting the hash to be "undefined" somehow makes it defined. 因此,以某种方式将哈希设置为“未定义”即可使其定义。 Is it defined as being "undefined"? 是否定义为“未定义”?

EDIT: 编辑:

This is an idealised case, in an attempt to replicate the problem. 这是一个理想的情况,试图重现该问题。 What I'm actually doing is more like: 我实际上正在做的更像是:

my %metadata = my_sub_function();
if (defined %metadata)
{
    print "defined";
}

Where the output of my_sub_function may be undef, () or a populated hash, and I only want to print "defined" in the last of these cases. 在my_sub_function的输出可能是undef,()或填充的哈希的情况下,我只想在最后一种情况下打印“ defined”。

EDIT 2: 编辑2:

Incidentally I have found that 偶然地我发现

if (scalar(keys %metadata)

behaves correctly for (), but still not for undef. 对于()行为正确,但对于undef仍然不正确。

Try 尝试

 my %metadata;
 undef %metadata;
 if (defined %metadata)
 {
     print "defined";
 }

I think it was just using a "undef" as data to populate the hash. 我认为它只是使用“ undef”作为填充哈希的数据。

"use warnings" would have said: “使用警告”可能会说:

defined(%hash) is deprecated at t.pl line 6.
    (Maybe you should just omit the defined()?)
Odd number of elements in hash assignment at t.pl line 4.
Use of uninitialized value in list assignment at t.pl line 4.

undef, () or a populated hash undef,()或填充的哈希

If you really want to distinguish between an empty hash and no hash, better use a hash reference (also lighter to pass around from the subroutine, no pass-by-copy and all). 如果您真的想区分是空散列还是没有散列,则最好使用散列引用(从子例程传递过来的内容也比较轻松,无须通过副本传递所有内容)。

If your function returns undef and that undef is placed in the hash, auto-stringification changes that undef to be '' and you end up with: %metadata = ( '' => undef ) . 如果您的函数返回undef并将该undef放置在哈希中,则自动字符串化会将undef更改为'' ,最后得到: %metadata = ( '' => undef )

If your function needs to return either undef , () or a proper hash and you need to test all three cases separately, I'd suggest: 如果您的函数需要返回undef()或适当的哈希值,并且需要分别测试所有三种情况,则建议:

my %metadata = my_sub_function();
if ( !scalar keys %metadata ) {
  print "An empty list () was returned\n"
} elsif (
  scalar keys %metadata == 1 and
  exists $metadata{''} and
  !defined $metadata{''}
) {
  print "undef or '' was returned\n";
} else {
  print "A hash was hopefully returned\n";
}

You could test it with the following my_sub_functions: 您可以使用以下my_sub_functions对其进行测试:

sub my_sub_function { return ()                 } # 1st case
sub my_sub_function { return undef              } # 2nd case
sub my_sub_function { return ( a => 1, b => 2 ) } # 3rd case
sub my_sub_function { return qw/not a hash/     } # unhandled case

Happy hacking 快乐黑客

if you see the documentation of defined , you will find that , 如果你看到的文档定义 ,你会发现,

When defined used on a hash element, 
it tells you whether the value is defined, 
not whether the key exists in the hash. 

try simple, if (%a_hash) { print "has hash members\\n" } 尝试简单, if (%a_hash) { print "has hash members\\n" }

Note: undef is the value of a variable that has never been initialized (or that has been reset using the undef function). 注意: undef是从未初始化(或已使用undef函数重置的)变量的值。 The defined function returns true if the value of the expression is not undef.

try this 尝试这个

%metadata=("1"=>"one");
undef %metadata;
if ( %metadata)
{
    print "defined";
}

And if you look at the documentation on perldoc -f defined , it says this ways of checking is deprecated. 并且,如果您查看perldoc -f defined上的文档,它说不赞成使用这种检查方法。

 Use of "defined" on aggregates (hashes and arrays) is deprecated. 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM