Lev*_*Lev 5 perl constants activeperl
我正在用Perl编写一个带有几个模块的应用程序.我想写一些从任何地方都可以看到的全局常量,如下所示:
#Constants.pm
$h0 = 0;
$scale = 20;
Run Code Online (Sandbox Code Playgroud)
然后使用它们而无需使用main::或Constants::在几个模块中进行限定.但是,如果我use Constants;在多个模块中编写,它们只会导入到一个名称空间中.有没有办法解决?
我正在使用最新的ActivePerl.
这段代码应该完全符合您的要求.将所有荣誉发送给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)
不要告诉任何我告诉过你的人,但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等)
但是,如果你在实际代码中执行此操作,那么期望有人谋杀你:)不过,最好知道,以防万一你看到其他人这样做.
您可以将其放在顶部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?