【问题标题】:Hash Constants in PerlPerl 中的哈希常量
【发布时间】:2010-12-06 19:16:49
【问题描述】:

我有一个应用程序,它映射到我需要在 zip 文件中处理的目录。映射很简单:

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

也就是说,如果文件名以CWA 开头,我就知道我要处理的目录在Financial 下。如果文件名以IFA 开头,我知道目录名是IFA。我想将其设置为哈希(很简单),但由于这些值并没有真正改变,我想将此键 => 值映射设置为哈希常量。

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

我正在考虑编写一个子程序,您可以在其中传递一个参数并返回正确的值。毕竟,这确实是常量本身的工作方式,它可以保证键和值之间的关系在整个程序中不会改变。

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

实现键 => 值常量的最佳方式是什么?

【问题讨论】:

    标签: perl constants


    【解决方案1】:

    您可以使用Const::Fast

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

    【讨论】:

    • 对 Const::Fast 的致谢:“这个模块的接口灵感来自 Eric Roode 的 Readonly。实现的灵感来自于 Readonly 的相反方式。”
    【解决方案2】:
    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()};
    };
    

    【讨论】:

    • 最好在函数外部定义 my %map,就在上面(以及调用代码的单独模块中的函数,以便隐藏 my 变量)。这样可以避免每次调用函数时不必要地重新初始化哈希。
    • 这是一个很好的观点。或者,在 5.10+ 中,使用 state,它提供了最好的隐藏,但仍然只初始化一次。
    • 第二个工作,但我必须做 {+shift}。否则,它将 {shift} 作为索引本身。
    【解决方案3】:

    或者,如果您不想使用块,您仍然可以使用常量:

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

    【讨论】:

      【解决方案4】:

      根据一些建议,我最终做了以下事情:

      {
          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

      【讨论】:

      • 为什么要关闭严格和警告? O_o
      • @antred ,启用严格和警告后,第一个 $appHash{CWA}(计数器)示例将不会编译。
      • 已编辑以在较小范围内禁用限制和警告。并添加了一个大警告来回答 @antred 的尖刻“O_o”评论
      • 嘿,这可能是一个尖刻的评论,但它确实让你回去改进你的答案。 ?
      猜你喜欢
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-20
      • 2013-08-10
      • 1970-01-01
      • 2011-06-14
      相关资源
      最近更新 更多