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

var*_*nie 0 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;
Run Code Online (Sandbox Code Playgroud)

谢谢.

Zai*_*aid 6

你可以用map:

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

如果我没有记错的话,那dirname就没必要了:

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

  • @varnie:如果你在余生中一天跑了一百次,它可能会加起来有足够的时间来引人注意. (2认同)

ike*_*ami 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',
};
Run Code Online (Sandbox Code Playgroud)

use FindBin qw( $RealBin );

use constant BAR_NAMES => {
    WATER => "$RealBin/../data/water.png",
    FIRE  => "$RealBin/../data/fire.png",
    GRASS => "$RealBin/../data/grass.png",
};
Run Code Online (Sandbox Code Playgroud)