2010-12-06 136 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"; 
更好