Хеш-константы в Perl - PullRequest
       3

Хеш-константы в Perl

9 голосов
/ 06 декабря 2010

У меня есть ситуация, когда у меня есть приложение, и оно отображается в каталог, который мне нужно обработать в zipfile.Сопоставление довольно простое:

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

То есть, если имя файла начинается с CWA, я знаю, что каталог, который мне нужно найти, находится под Financial.Если имя файла начинается с IFA, я знаю, что имя каталога - IFA.Я хотел бы установить это как хеш (достаточно просто), но так как эти значения на самом деле не меняются, я бы хотел установить это отображение ключа => значения как хеш-константу.

Iне верю, что это возможно, поэтому я хотел бы сделать следующее лучшее.Что бы это было?Или вы можете установить хеш-константу?

Я думаю о написании подпрограммы, в которой вы передаете параметр, и он возвращает правильное значение.В конце концов, именно так работают сами константы, и это гарантирует, что отношения между ключами и значениями не изменятся во всей программе.

Или я могу просто объявить значение key =>отношения в начале моей программы и надеюсь, что пары ключ => значение не изменяются чем-то.Это было бы проще для чтения и проще для изменения, если бы вам пришлось это делать, так как оно находится в самом верху моего исходного кода.

Каков наилучший способ реализации константы значения key =>?

Ответы [ 4 ]

9 голосов
/ 06 декабря 2010

Вы можете использовать Const::Fast.

use Const::Fast;
const my %hash = (
    CWA => "Financial",
    PIP => "",
    IFA => "IFA",
    VDX => "Financial",
);
9 голосов
/ 06 декабря 2010
  1. Просто используйте именованный хеш.Скорее всего, ничего не пойдет не так.

  2. Использование Только чтение .Это делает хеш доступ к нему, как и к любому другому хешу, но его нельзя изменить, пока кто-то не начнет перебирать внутренние компоненты 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()};
};
2 голосов
/ 07 декабря 2010

Вот что я наконец-то сделал, выполнив несколько предложений:

{
    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

Аккуратно!

Спасибо iwj и hobbs

1 голос
/ 01 февраля 2017

В качестве альтернативы, если вы не хотите использовать блоки, вы все равно можете использовать константу:

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";
...