Precalculate Perl常量基于某些运行时计算值

时间:2013-09-11 14:55:41

标签: perl constants

这应该是相当微不足道的,但我无法自己解决这个问题。 有了下面的代码,有没有办法摆脱dirname(rel2abs($0))的许多调用?

package Foo;

use File::Basename;
use File::Spec::Functions qw/rel2abs/;
use Carp qw/croak/;
use 5.010;

use constant BAR_NAMES => {
    WATER => dirname(rel2abs($0)) . '/../data/water.png',
    FIRE => dirname(rel2abs($0)) .'/../data/fire.png',
    GRASS => dirname(rel2abs($0)) .'/../data/grass.png'#,
    #and so on
};

sub get {
    my ($self, $name) = (shift, shift);
    if (exists BAR_NAMES->{$name}) {
        #return some calculated data based on $name value
    } else {
        croak("Constant `$name` is not declared.");
    }
};

1;

谢谢。

4 个答案:

答案 0 :(得分:6)

您可以在map

中滚动它
use constant BAR_NAMES =>
{
   map { uc( $_ ) => dirname(rel2abs($0)) . "/../data/$_.png" }
     qw< water fire grass >
};

如果我没弄错的话,dirname不一定是必要的:

use constant BAR_NAMES =>
{
   map { uc( $_ ) => rel2abs("$0/../data/$_.png") }
     qw< water fire grass >
};

答案 1 :(得分:5)

除了现有的答案之外,还有

use constant PROJ_ROOT => dirname(rel2abs($0)) . '/..';

use constant BAR_NAMES => {
    WATER => PROJ_ROOT.'/data/water.png',
    FIRE  => PROJ_ROOT.'/data/fire.png',
    GRASS => PROJ_ROOT.'/data/grass.png',
};

use FindBin qw( $RealBin );

use constant BAR_NAMES => {
    WATER => "$RealBin/../data/water.png",
    FIRE  => "$RealBin/../data/fire.png",
    GRASS => "$RealBin/../data/grass.png",
};

答案 2 :(得分:3)

my $dirname;
BEGIN { $dirname = dirname(rel2abs($0)); }

use constant BAR_NAMES => {
    WATER => $dirname . '/../data/water.png',
    FIRE => $dirname .'/../data/fire.png',
    GRASS => $dirname .'/../data/grass.png'#,
    #and so on
};

您需要一个BEGIN块,因为use语句中的任何表达式都是在编译时计算的。

答案 3 :(得分:3)

use constant BAR_NAMES => do {
    my $dirname = dirname(rel2abs($0));
    {
        WATER => $dirname . '/../data/water.png',
        FIRE => $dirname .'/../data/fire.png',
        GRASS => $dirname .'/../data/grass.png'#,
        #and so on
    }
};