【问题标题】:How can I import constants into multiple modules in Perl?如何将常量导入 Perl 中的多个模块?
【发布时间】:2010-10-06 05:55:34
【问题描述】:

我正在用 Perl 编写一个包含多个模块的应用程序。我想写一些在任何地方都可见的全局常量,像这样:

#Constants.pm
$h0 = 0;
$scale = 20;

然后在几个模块中使用它们而不用main::Constants:: 限定。但是,如果我在多个模块中编写use Constants;,它们只会被导入到一个命名空间中。有没有办法解决这个问题?

我正在使用最新的 ActivePerl。

【问题讨论】:

    标签: perl constants activeperl


    【解决方案1】:

    你可以把这个放在Constants.pm的顶部:

    package main;
    

    在这种情况下,您定义的所有变量都将位于 main 命名空间中:

    $main::x
    

    或者如果你觉得很勇敢:

    package;
    

    在这种情况下,您定义的所有变量都将位于一个空的命名空间中:

    $::x
    

    请注意,不鼓励使用没有命名空间的package,并且显然在某些版本的 Perl 中将被弃用。请参阅下面的报价。


    引用man perlfunc:

    包命名空间 package 将编译单元声明为在给定的 命名空间。包声明的范围是 从声明本身到结束 封闭块、文件或 eval(与“my”相同) 操作员)。所有其他不合格的动态标识符 将在此命名空间中。包声明影响 只有动态变量——包括你使用过的变量 “local” on--但不是词法变量,它们是 cre? 与“我的”一起吃。通常它会是第一个声明? 配给文件中的“要求”或 “使用”运算符。您可以在更多中切换到一个包 不止一处;它只影响哪个符号表 由编译器用于该块的其余部分。 您可以参考其他变量和文件句柄 通过在标识符前面加上包的前缀来打包 名称和双冒号:$Package::Variable。如果 包名称为空,假定为“主”包。 也就是说,$::sail 等价于 $main::sail(同样 至于 $main'sail,仍然可以在旧代码中看到)。 如果 NAMESPACE 被省略,那么没有当前包? 年龄,并且所有标识符必须是完全限定的或 词汇。但是,强烈建议您不要 使用此功能。它的使用可能会导致意外 行为,甚至使某些版本的 Perl 崩溃。它是 已弃用,并将从将来的版本中删除。

    编辑:这个问题也可能有帮助:How do I use constants from a Perl module?

    【讨论】:

    • 谢谢。我真正需要的是关于省略“main”的部分。
    • 我很好奇它是否真的有效。如果是这样,我将删除答案顶部的免责声明。
    • 这会将常量放在 main:: 中,但是现在您必须在所有常量前面加上 main::
    • 内森:它有效。 Brian:不,你只需要在它们前面加上 $::。这是可以忍受的。
    • FWIW,Perl 5.10 拒绝解析“package;”。
    【解决方案2】:

    查看Exporterperlmod 手册页。

    【讨论】:

      【解决方案3】:

      不要告诉任何人我告诉过你这个,但是 Perl 的特殊变量是 随处可用。你可能已经注意到这并不 工作:

      { package Foo;
      our $global = 42; }
      
      { package Bar;
      say "global is $global"; }
      

      那是因为$global 实际上被称为$Foo::global。你已经 也可能注意到这个“规则”不适用于像 @INC%ENV$_ 等。那是因为这些变量总是 假设在main

      但实际上,不仅仅是这些变量。整个球体 被“强制”进入main。这意味着你可以写类似 这个:

      { package Constants;
        $_{PI} = 3.141592; }
      
      { package Foo;
        say "pi is $_{PI}"; }
      

      它会起作用的。

      (同样适用于$ENV&INC等)

      但是,如果您曾经在真实代码中执行此操作,那么预计有人会谋杀您 :) 很高兴知道,以防万一你看到别人 这样做。

      【讨论】:

        【解决方案4】:

        你可以像这样使用Exporter

        在常量.pm 中:

        #Constants.pm require Exporter; @ISA = qw(Exporter); @EXPORT = qw($h0 $scale); @EXPORT_OK = qw(myfunc); $h0 = 0; $scale = 20; sub myfunc {...}

        注意事项:
        * &myfunc 中的& @EXPORT 数组中的& 是可选的,建议不要使用。 * 这将默认导出$h0$scale,并且只有在明确请求时才导出&myfunc(见下文如何指定客户端模块导入的符号)

        然后在导入 Constants.pm 并希望使用 $h0$scale&myfunc 的模块中添加以下内容以导入 @987654331 中的 所有 符号@ in Constants.pm。

        #MyModule.pm use Constants qw(;

        如果您只想导入部分符号,请使用:

        #MyModule.pm use Constants qw($h0);

        最后,如果您不想导入任何 Constant.pm 的符号,请使用:

        #MyModule.pm use Constants ();

        【讨论】:

          【解决方案5】:

          这段代码应该完全符合您的要求。将所有荣誉发送至lkundrak

          package Constants;
          
          use base qw/Exporter/;
          
          use constant BOB => 666;
          use constant ALICE => 555;
          
          sub import {
              no strict "refs";
          
              ${[caller]->[0].'::'}{$_} = ${__PACKAGE__."::"}{$_}
                  foreach grep { not /^(ISA|isa|BEGIN|import|Dumper)$/ } 
                      keys %{__PACKAGE__."::"};
          }
          

          【讨论】:

          • 有趣的是,这是处理常量的唯一答案(甚至问题实际上并没有触及它们)。
          猜你喜欢
          • 1970-01-01
          • 2011-11-06
          • 2010-09-16
          • 1970-01-01
          • 2015-10-20
          • 2012-09-11
          • 2018-04-28
          • 2011-04-06
          • 1970-01-01
          相关资源
          最近更新 更多