用perl初始化常量变量

时间:2014-01-28 18:49:58

标签: perl

我有以下常数:

use constant => 7

是否有一个选项可以通过标量变量设置常量一次,然后常量的值将是初始化值,即如下所示:

use constant => $scalar - >那么从现在开始的常数在这一点上具有标量值

任何建议?

3 个答案:

答案 0 :(得分:7)

使用use constant创建的常量在编译时处理,因此$scalar变量可能尚未分配任何值。

然而,您可以使用Const::Fast模块制作标量 - 井 - 常数:

use Const::Fast;

my $scalar = 7;
const my $constant => $scalar;
$constant = 42; # dies

这比use constant更可取,因为它处理const标量比处理常量(实现为特殊子程序)更好。例如,可以将const标量插入到字符串中。

但是,编译时常量参与常量折叠优化。在某些情况下,这实际上是必要的,因此use constant的一些用途仍然存在。

(如果你不能使用Const::Fast,那么Readonly是另一种选择,虽然速度较慢)

答案 1 :(得分:4)

是的,你可以。当然,您必须尽快将值分配给标量。

my $foo;
BEGIN {
   ...
   ...
   $foo = ...;
}
use constant FOO => $foo;

您也可以使用do

use constant FOO => do {
   ...
   ...
   ...
};

答案 2 :(得分:2)

通过创建一个返回常量值的子例程,在编译时创建常量。

例如:

 use constant PI => 3.1415169;

与此类似:

sub PI {
    return 3.1415169;
}

问题是常量很难在各种情况下使用,例如正则表达式或带引号的字符串。有一种秘密的,模糊的内插常量的方法(这种方法也适用于其他类型的子程序。你可以在@{[...]}内嵌入常量:

say "The value of pi is equal to @{[PI]}.";

# Replace value of Pi in Alabama: http://www.snopes.com/religion/pi.asp

$foo = s/@{[PI]}/3/g;

丑陋不是吗?

另一种方法是使用类型globs:

*PI = \3.1415926;
our $PI;

这会插入:

say "The value of pi is $PI."

但是,除了标量之外的其他任何东西都不能很好地运作。您可以定义数组和散列,但它们不是常量值。

幸运的是,有许多方法可以定义更像变量的常量。不幸的是,有很多种方法来定义更像变量的常量,并且Perl没有附带的标准模块。这意味着您必须在需要运行脚本的每个系统上安装一些可选的CPAN模块。如果它们在公司服务器上,您可能需要有人为您安装模块。

另外,由于每个人都有自己喜欢的常规例程,因此最终可能会安装多个模块:

最受欢迎的是Readonly

use Readonly;

# For Perl 5.8 and later...
Readonly my $pi => 3.1415926;

它快速而简单,但Readonly可能很慢,除非你也安装了Readonly:XS,如果你没有C编译器和Make,那么Readonly :: XS可能很难安装。一个名为Const::Fast的新模块也很受欢迎:

use Const::Fast;
const my PI => 3.1415926;

say "The value of pi is $pi.";

所以,你有它。

  • 您可以使用use constant;这是一个标准模块,因此您知道它始终可用。但是,它不容易插值。您可以使用@{[...]}语法,但这很难看。
  • 你可以使用几乎任何版本的Perl工作的typglobs,不需要可选模块。 Typeglobs会进行插值,但定义语法只是可怕的。此外,它们不适用于阵列和散列。
  • 您可以使用Readonly或Const :: Fast,但必须在脚本运行之前通过CPAN安装它们,这在某些情况下可能会很困难。