我想从配置文件中创建perl-constants。我使用Config :: File来读取如下所示的配置文件:
ABC = DEF
GHI = JKL
使用Config :: File创建一个如下所示的hashref:
$VAR1 = {
'ABC' => 'DEF',
'GHI' => 'JKL'
};
我想使用hashref来创建常量,其中常量的名称应该是键,值应该是hashref中的对应值。手动我会做类似
的事情use constant ABC => 'DEF';
use constant GHI => 'JKL';
我尝试过这样做:
foreach my $const (keys %$hashref) {
use constant $const => $keys->{$const};
}
但正如预期的那样无效。有没有办法实现我想要做的事情?
答案 0 :(得分:5)
我发布这个作为答案,从评论中提取 - 哈希与常数:
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
use Benchmark qw(:all);
use constant ABC => 'DEF';
use constant GHI => 'JKL';
my $ABC = 'DEF';
my $GHI = 'JKL';
my %test_hash = (
ABC => 'DEF',
GHI => 'JKL'
);
sub access_hash {
my $value = $test_hash{ABC};
my $value2 = $test_hash{DEF};
}
sub access_constant {
my $value = ABC;
my $value2 = GHI;
}
sub access_scalar {
my $value = $ABC;
my $value2 = $GHI;
}
my $count = 100_000_000;
cmpthese(
$count,
{ 'hash' => \&access_hash,
'constant' => \&access_constant,
'scalar' => \&access_scalar
}
);
结果:
Rate hash scalar constant
hash 9427736/s -- -7% -10%
scalar 10143017/s 8% -- -3%
constant 10492078/s 11% 3% --
所以你是对的 - 使用常数会更快。但是,我建议以10M /秒的速度运行,然后保存' 5%(甚至10%)根本不值得你需要做的hackery。
但为了实际回答这个问题 - 这个问题的根源是constant
是在编译时定义的,其中变量......不是。
定义constant
时,根本没有哈希存在,因此无法正常工作。您在BEGIN
区块中实际执行的操作也非常有限。我的想法是你可能可能运行一个'编译'将配置文件转换为.pm
然后use
的过程。
package import_const;
use constant ABC => 'DEF';
use constant GHI => 'JKL';
然后use import_const;
并以import_const::ABC
的形式访问您的常量。 (或使用Exporter
将它们带入本地命名空间)。
sub from_pkg {
my $value = import_const::ABC;
my $value2 = import_const::GHI;
}
将其添加到计时测试中:
Rate hash scalar imported constant constant
hash 9497578/s -- -6% -9% -9%
scalar 10063399/s 6% -- -4% -4%
imported constant 10473398/s 10% 4% -- -0%
constant 10492078/s 10% 4% 0% --
我认为我仍然认为努力的收益微不足道。特别是use constant will surprise you with it's evil
可能有一个模块可以做你需要的事情:
答案 1 :(得分:4)
首先,你可以做到
use constant {
CONST1 => VAL1,
CONST2 => VAL2,
...
};
use constant LIST
相当于
BEGIN {
require constant;
constant->import(LIST);
}
或
use constant qw( );
BEGIN {
constant->import(LIST);
}
所以你可以做到
use constant qw( );
use FindBin qw( $RealBin );
use JSON::XS qw( decode_json );
BEGIN {
my $qfn = "$RealBin/constants.json";
open(my $fh, '<:raw', $qfn) or die $!;
my $file; { local $/; $file = <$fh>; }
my $constants = decode_json($file); # { 'ABC' => 'DEF', 'GHI' => 'JKL' };
constant->import($constants);
}
更清洁的解决方案可能是使用迷你模块。
package MyConstantsFromFile;
use strict;
use warnings;
use constant qw( );
use JSON::XS qw( decode_json );
sub import {
my $class = shift;
my $qfn = shift;
open(my $fh, '<:raw', $qfn) or die $!;
my $file; { local $/; $file = <$fh>; }
my $constants = decode_json($file); # { 'ABC' => 'DEF', 'GHI' => 'JKL' };
my $import = constant->can('import');
@_ = ('constant', $constants);
goto &$import;
}
1;
use FindBin qw( $RealBin );
use MyConstantsFromFile "$RealBin/constants.json";