在Perl中使用常量

时间:2010-06-16 20:44:16

标签: perl constants

我正在尝试使用constant pragma:

在Perl中定义常量
use constant {
    FOO => "bar",
    BAR => "foo"
};

我遇到了一些麻烦,并希望有一种标准的处理方法。

首先......

我正在为Subversion定义一个钩子脚本。为了简单起见,我希望有一个文件,我正在使用的类(包)与我的实际脚本在同一个文件中。

这个包中的大多数都会包含常量:

 print "This is my program";

 package MyClass;

 use constant {
    FOO => "bar"
 };

 sub new { ... }

我希望我的常规FOO能够被我的主程序访问。我想这样做而不必将其称为MyClass::FOO。通常,当包是一个单独的文件时,我可以在我的主程序中执行此操作:

use MyClass qw(FOO);

但是,由于我的课程和程序是单个文件,我不能这样做。我的主程序能够访问我班级中定义的常量的最佳方法是什么?

第二个问题......

我想将常量值用作哈希键:

$myHash{FOO} = "bar";

问题是%myHash将文字字符串FOO作为键而不是常量的值。当我做这样的事情时,这会导致问题:

if (defined $myHash{FOO}) {
   print "Key " . FOO . " does exist!\n";
}

我可以强制上下文:

if (defined $myHash{"" . FOO . ""}) {

我可以添加括号:

if (defined $myHash{FOO()}) {

或者,我可以使用临时变量:

my $foo = FOO;
if (defined $myHash{$foo}) {

这些都不是解决此问题的好方法。那么,最好的方法是什么?有没有一种我错过的方式?

顺便说一句,我不想​​使用Readonly::Scalar,因为它是1)。慢,2)。不属于标准Perl包。我想定义我的钩子,不要求额外的Perl包,并尽可能简单地工作。

4 个答案:

答案 0 :(得分:20)

如果要将所有内容保存在同一个文件中,可以按如下方式定义常量包:

use warnings;
use strict;

BEGIN {  # BEGIN means this will all happen at compile time
    package Constants;

    $INC{'Constants.pm'}++;     # tell `require` that the package is loaded
    use base 'Exporter';        # setup package to export
    our @EXPORT_OK = qw( PI );  # what to export

    use constant PI => 3.14159; # define your constant
}

package main;

use Constants qw( PI );  # use it like normal

print PI;

然后愚弄自动引用内部哈希下标,您可以这样写:$hash{+PI}$hash{(PI)}$hash{PI()}$hash{&PI}$hash{::PI} ......我可能继续前进,但我认为你明白了。

需要$INC{'Constants.pm'}++的原因是因为use Constants qw( PI );行确实意味着:

BEGIN {
    require 'Constants.pm';
    Constants->import( qw( PI ) );
}

require将检查%INC以查看是否已加载包。因此,通过给它一个真值(在这种情况下为1),require 'Constants.pm';的{​​{1}}部分将成为无操作。

答案 1 :(得分:4)

  1. Perl constants不是常量。它们被编译定义为在编译时内联的特定类型的函数。

  2. 我发现Perl'常数'比使用更痛苦。因此,通常我的方法是使用全部大写的标量。 my $PI = 3.14159;

答案 2 :(得分:3)

当Barewords出现在哈希查找中时会自动引用它们。您需要强制调用实现常量的sub:

$myHash{FOO}   = 'bar'; # doesn't work, bareword quoted
$myHash{+FOO}  = 'bar'; # okay
$myHash{&FOO}  = 'bar'; # okay
$myHash{FOO()} = 'bar'; # okay

将函数和变量从一个包导出到另一个包是符号表操作。 Exporter模块让我们很容易,但没有模块就不难做到。

package main;
sub stuff { return &FOO x 3 }
*FOO = *MyClass::FOO;
print stuff();               # "barbarbar"

package MyClass;
use constant FOO => "bar";

你也可以说

BEGIN { *main::FOO = *FOO }
<{1>}下的

答案 3 :(得分:0)

我的第二个Eric Strom回答。

但是,这是另一种方式(但是暴露了太多的Perl实现):

use strict;
use warnings;

package Constants;
sub FOO() { 'bar' }
sub BAR() { 'foo' }
sub main::FOO() { FOO }
sub main::BAR() { BAR }

package main;

print FOO, BAR, "\n";