如何在Perl中将常量导入多个模块?

Lev*_*Lev 5 perl constants activeperl

我正在用Perl编写一个带有几个模块的应用程序.我想写一些从任何地方都可以看到的全局常量,如下所示:

#Constants.pm
$h0 = 0;
$scale = 20;
Run Code Online (Sandbox Code Playgroud)

然后使用它们而无需使用main::Constants::在几个模块中进行限定.但是,如果我use Constants;在多个模块中编写,它们只会导入到一个名称空间中.有没有办法解决?

我正在使用最新的ActivePerl.

Joe*_*nte 7

查看Exporterperlmod手册页.


Mic*_*eli 7

这段代码应该完全符合您的要求.将所有荣誉发送给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__."::"};
}
Run Code Online (Sandbox Code Playgroud)


jro*_*way 5

不要告诉任何我告诉过你的人,但Perl的特殊变量随处可见.您可能已经注意到这不起作用:

{ package Foo;
our $global = 42; }

{ package Bar;
say "global is $global"; }
Run Code Online (Sandbox Code Playgroud)

那是因为$global实际上被称为$Foo::global.你也可能注意到,这个"规则"并不适用于像的东西 @INC,%ENV,$_等等.这是因为这些变量总是假定为main.

但实际上,它不仅仅是那些变量.整个glob被"强制"进入main.这意味着你可以这样写:

{ package Constants;
  $_{PI} = 3.141592; }

{ package Foo;
  say "pi is $_{PI}"; }
Run Code Online (Sandbox Code Playgroud)

它会起作用.

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

但是,如果你在实际代码中执行此操作,那么期望有人谋杀你:)不过,最好知道,以防万一你看到其他人这样做.


Nat*_*man 2

您可以将其放在顶部Constants.pm

package main;
Run Code Online (Sandbox Code Playgroud)

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

$main::x
Run Code Online (Sandbox Code Playgroud)

或者如果你感觉勇敢:

package;
Run Code Online (Sandbox Code Playgroud)

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

$::x
Run Code Online (Sandbox Code Playgroud)

请注意,不鼓励使用package不带名称空间的方法,并且在某些版本的 Perl 中显然会弃用这种方法。请参阅下面的引用。


引用自man perlfunc

       包命名空间
       package 将编译单元声明为给定的
               命名空间。包声明的范围是
               从声明本身到声明结束
               封闭块、文件或 eval(与“my”相同)
               操作员)。所有进一步的不合格动态标识符
               将位于此命名空间中。包声明影响
               仅动态变量——包括您使用过的变量
               “本地” - 但不是词法变量,这是cre?
               和“我的”一起吃饭。通常这将是第一个声明?
               文件中的配给由“require”或
               “使用”运算符。可以切换成更多的包
               不止一处;它仅仅影响哪个符号表
               编译器将其用于该块的其余部分。
               您可以在其他中引用变量和文件句柄
               通过在标识符前添加包前缀来进行包
               名称和双冒号:$Package::Variable。如果
               包名称为空,假定为“主”包。
               也就是说, $::sail 等价于 $main::sail (以及
               至于 $main'sail,在旧代码中仍然可见)。

               如果省略 NAMESPACE,那么当前包就没有了?
               年龄,并且所有标识符必须完全合格或
               词汇。但是,强烈建议您不要
               利用这个功能。它的使用可能会导致意想不到的
               行为,甚至导致某些版本的 Perl 崩溃。这是
               已弃用,并将从未来版本中删除。


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