挂钩为Perl中的每个Hash查找提供一个值

时间:2015-04-28 12:08:46

标签: perl hash

是否可以在Perl中提供一个钩子以确保没有Hash密钥查找失败?

示例:

use strict; 
use warnings; 
my %hash_example = ( "a"=>"apple", "b"=>"ball" ); 
print $hash_example{"a"};  # Goes Fine. 
print $hash_example{"c"};  # Throws Warning  ( "Use of uninitialized value " ).

Codepad link

每当发生哈希查找时,可以调用某个子例程,它可以提供默认值。

我的意思是,任何哈希查找都应该调用一个sub(比如“get_hash_value (hash_ref, key)”)并将哈希和密钥传递给它。这样一个子样本如下所示:

sub get_hash_value { 
    my $hash_ref = shift; 
    my $key      = shift; 
    if ( exists $hash_ref->{$key} ) { # For Normal Lookup. 
        return $hash_ref->{$key}; 
    } 
    else { 
        # This is the interesting place where we could provide our own values. 
        return "custom_value_based_on_certain_conditions";  # Some value 
    } 
}

另一个结果是能够改变针对密钥返回的值。我们将能够返回与该键存储的实际值不同的值(在该哈希值中)。

可能没有一个有效的用例,但我很感兴趣,并希望了解Perl是否支持这些内容。

3 个答案:

答案 0 :(得分:3)

正如Сухой27在评论中所说,这很好用:

my %hash_example = ( "a"=>"apple", "b"=>"ball" ); 
print $hash_example{"a"};  
print $hash_example{"c"} // "custom_value_based_on_certain_conditions";

Doc logical defined or

答案 1 :(得分:2)

我建议尝试改变散列查找“工作”的方式是一个非常糟糕的想法,作为创建难以维护的代码的好方法。

但是我会建议您查看创建对象而不是哈希。它们基本上是相同的,但是一个对象包含代码,并且有一个期望,对象中的代码是“做它自己的事情”。

所以在基本层面:

#!/usr/bin/env perl

use strict;
use warnings;

package Hash_Ob;

sub new {
    my ($class) = @_;
    my $self = {};
    bless( $self, $class );
    return $self;
}

sub get_value {
    my ( $self, $valuename ) = @_;
    if ( $self->{$valuename} ) {
        return $self->{$valuename};
    }
    else {
        #generate your own value here!
        $self->{$valuename} = 42;
        return $self->{$valuename};
    }
}

1;

然后使用以下方式“呼叫”:

#!/usr/bin/env perl

use strict;
use warnings;

use Hash_Ob;

my $magic_hash = Hash_Ob -> new();

print $magic_hash -> get_value('new_value');

这避免了改变“众所周知”机制实际工作方式的问题,因此未来的维护程序员不会诅咒你的名字。

答案 2 :(得分:2)

那么也许你想使用绑定哈希。绑定是一种改变内置数据类型行为的机制。有关血腥的详细信息,请参阅perltie

{
    package HashWithDefault;
    use Tie::StdHash;
    our @ISA = qw(Tie::StdHash);    # inherit STORE, FIRST, NEXT, etc.
    sub TIEHASH {
        my ($pkg,$default_val) = @_;
        return bless { __default_val__ => $default_val}, $pkg;
    }
    sub FETCH {
        my ($self,$key) = @_;
        exists $self->{$key} ? $self->{$key} : $self->{__default_val__};
    }
    sub CLEAR {  # don't clear the default val
        my $self = shift;
        %$self = ( __default_val__ => $self->{__default_val__} );
    }
}

tie my %hash, 'HashWithDefault', "42";
%hash = (foo => 123, bar => 456);
print $hash{foo};   # 123
print $hash{quux};  # 42