2010-12-06 162 views
9

我有一种情况,我有一个应用程序,它映射到我需要在zipfile中处理的目录。映射很简单:Perl中的哈希常量

CWA => "Financial", 
PIP => "", 
IFA => "IFA", 
VDX => "Financial, 

也就是说,如果该文件的名称与CWA开始,我知道我必须Munge时间目录是Financial下。如果文件名以IFA开头,我知道目录名称是IFA。我想把它设置为散列(很简单),但是由于这些值并没有真正改变,所以我想将这个key =>值映射设置为散列常量。

我不相信这是可能的,所以我想做下一件好事。那会是什么?或者,你可以设置一个哈希常量?

我想写一个子程序,你传递一个参数,它返回正确的值。毕竟,常量本身就是这样工作的,它确保了键和值之间的关系不会在整个程序中发生变化。

或者,我可以简单地在我的程序开始处声明key => value关系,并希望key => value对不会被某些东西修改。这样会更容易阅读,并且如果您必须修改,则更容易,因为它位于我的源代码的顶部。

实现key => value constant的最佳方式是什么?

回答

9
  1. 只要使用一个命名散列。很有可能,没有什么会出错的。

  2. 使用Readonly。这使得像任何其他散列一样访问散列,但不能被修改,除非有人开始在perl内部打开。正如其文档中所述,与常规变量访问相比,速度很慢,但它不太可能足够慢以至于不能满足您的需求。

  3. 将散列隐藏在子程序中。

sub get_directory_for_prefix { 
    my ($prefix) = @_; 
    my %map = (
     CWA => "Financial", 
     PIP => "", 
     IFA => "IFA", 
     VDX => "Financial", 

    ); 
    return $map{$prefix}; 
} 

甚至

sub get_directory_for_prefix { 
    {CWA=>"Financial",PIP=>"",IFA=>"IFA",VOX=>"Financial"}->{shift()}; 
}; 
+0

定义函数外的我的%映像,正上方(和该函数在调用代码的单独模块中,以便隐藏我的变量)。这可以避免每次调用函数时不必要的重新初始化哈希。 – ijw 2010-12-06 19:53:23

+0

这是一个很好的观点。或者,在5.10+中,使用`state`,它提供了最好的隐藏,但仍然只初始化一次。 – hobbs 2010-12-06 20:28:37

+0

第二个作品,但我不得不{{shift}。否则,它需要{shift}作为索引本身。 – 2010-12-06 21:03:52

7

您可以使用Const::Fast

use Const::Fast; 
const my %hash = (
    CWA => "Financial", 
    PIP => "", 
    IFA => "IFA", 
    VDX => "Financial", 
); 
2

这里是我最后还是以下几点建议:

{ 
    my %appHash = (
     CWA => "Financial", 
     PIP => "", 
     FIA => "FIA", 
     VDX => "Financial", 
    ); 

    sub appDir { 
     return $appHash{+shift}; 
    } 
} 

通过将%appHash自己的块,我不能引用哈希在我的代码的其余部分。但是,appDir子例程位于同一个块中并且可以引用它。而且,由于子程序是封装广泛的,我可以在我的代码中访问该子程序。因此,我可以访问%appHash的值,但我无法更改它们。

use strict; 
use warnings; 
{ 
    my %appHash = (
     CWA => "Financial", 
     PIP => "", 
     FIA => "FIA", 
     VDX => "Financial", 
    ); 

    sub appDir { 
     return $appHash{+shift}; 
    } 
} 

{ 
    ### WARNING. 
    ### this code is a counter example to show that %appHash 
    ### is not available in this scope. 
    ### Do not use this code. 
    ### Disabling strictures and warnings in this block only. 

    no strict; 
    no warnings; # Danger Will Robinson! 
    # disable explicit package name error because %appHash is not defined in this scope. 
    # disable warnings related to 1) main::appHash and 2) uninitialized value of $appHash{"CWA"} 

    print "The directory for CWA is " . $appHash{CWA} . "\n"; #Prints nothing 
} 
print "The directory for CWA is " . appDir("CWA") . "\n"; #Prints Financial 

my %appHash; 
$appHash{CWA} = "FOO FOO FOO!"; 

print "The directory for CWA is " . $appHash{CWA} . "\n"; #Prints FOO FOO FOO! 
print "The directory for CWA is " . appDir("CWA") . "\n"; #Still prints Financial 

整洁!

感谢iwjhobbs

1

Alternativelly,如果你不想使用块,你可以仍然使用常数:

use strict; 
use warnings; 

use constant CONSHASH => sub {{ 
    foo1 => 'bar1', 
    foo2 => 'bar2', 
    foo3 => 'bar3', 
}->{ +shift }}; 

print CONSHASH->('foo1') . "\n"; 
print CONSHASH->('foo2') . "\n"; 
print CONSHASH->('foo3') . "\n"; 
更好