尝试访问未定义的散列键时使perl发出呼喊

尝试访问未定义的散列键时使perl发出呼喊,perl,hash,Perl,Hash,我认为这个标题是不言自明的。很多时候,我会有一些小的输入错误,当我试图访问未定义的散列键时,会得到意想不到的结果。我知道我可以在每次访问哈希键之前添加一些定义的检查,但我想知道是否有更干净的方法来警告这种情况 最好的, Dave使用哈希::Util: use Hash::Util "lock_keys"; my %hash = (foo => 42, bar => 23); lock_keys(%hash); print $hash{foo}; print $hash{baz}; p

我认为这个标题是不言自明的。很多时候,我会有一些小的输入错误,当我试图访问未定义的散列键时,会得到意想不到的结果。我知道我可以在每次访问哈希键之前添加一些
定义的
检查,但我想知道是否有更干净的方法来警告这种情况

最好的, Dave

使用哈希::Util:

use Hash::Util "lock_keys";
my %hash = (foo => 42, bar => 23);
lock_keys(%hash);
print $hash{foo};
print $hash{baz};
print $hash{bar};
输出:

42
Attempt to access disallowed key 'baz' in a restricted hash at foo line 5.

还有其他函数允许指定要允许的键,而不仅仅是默认设置为已经存在的键。

您可以为此编写一个简单的函数:

sub get {
    my ($hash, $key) = @_;
    die "No such key: $key" unless exists $hash->{$key};
    return $hash->{$key};
}

my %hash = (...);    
my $val = get(\%hash, "mykey");

这可能最好用绑定的散列来完成。绑定变量允许您定义变量的低级操作的实现。在这种情况下,我们需要一种特殊的获取方法,该方法在访问不存在的密钥时失效:

use warnings;
use strict;

{package Safe::Hash;
        require Tie::Hash;
        our @ISA = 'Tie::StdHash';
        use Carp;

        sub FETCH { 
                exists $_[0]{$_[1]} or croak "no key $_[1]";
                $_[0]{$_[1]}
        }
}

tie my %safe => 'Safe::Hash';

$safe{a} = 5;  # ok

print $safe{a}, "\n";  # ok

$safe{b} = 10; # ok 

print $safe{bb}, "\n";  # dies
在上面的
Safe::Hash
实现中,我首先加载
Tie::Hash
,它提供了
Tie::StdHash
。将
@ISA
设置为
Tie::StdHash
为我们的新包提供了与普通哈希相同的Tie方法。上概述了每种tie方法


在这种情况下,唯一要覆盖的方法是
FETCH
,它传递了一个对隐藏绑定对象的引用(在这种情况下是hashref)和要使用的键。它检查插槽是否存在,然后返回插槽或抛出错误

谢谢,这很好,但我想知道是否有更适合我需要的插槽。我希望每次尝试访问未定义的密钥时都会生成一个错误,除非访问是一个赋值。我的散列是动态的-我一直在添加密钥和获取密钥-因此使用hash::Util将使我不断锁定和解锁,我还可以检查密钥是否已定义。@David B:那么您可能想使用绑定散列,正如Eric Strom建议的那样。虽然我想知道你到底在用你得到的价值观做什么?假设您启用了警告,许多操作应该已经对未定义的值发出警告。非常酷!你能解释一下取货部分吗?这是保留字吗?绑定变量提供了一组方法供您重写,允许您指定其行为。有关所有详细信息,请参阅perltie:您的意思不是检查键是否定义了
,而是检查它是否存在
。本质上没有未定义的散列键。@pilcrow感谢您的更正。