如何将参数传递给使用eval定义的Perl子例程?

gvk*_*vkv 4 parameters perl eval subroutine

我正在使用配置文件(在YAML中)来定义稍后用于验证我的应用程序所需的其他配置值的类型:

---
action: >
        use List::MoreUtils;
        my $value = $_;
        any { $value eq $_ } qw(fatal keep merge non-fatal replace);
dir   : return defined $_ ? -d $_ : -1;
file  : return defined $_ ? -f $_ : -1;
string: 1;


---
config-element:
    value: foo
    type : file
etc ...
Run Code Online (Sandbox Code Playgroud)

我们的想法是eval每个类型定义,将它们抛入哈希,然后调用验证配置数据(以下是易于理解的示意图):

#throw sub refs into hash
my %type_sub;
foreach my $key (keys %$type_def_ref) {
    my $sub_str = "sub {$type_def_ref->{$key}}";
    $type_sub{$key} = eval $sub_str;

}

#validate (myfile is a real file in the cwd)
print $type_sub{file}->('myfile'),"\n";
print $type_sub{action}->('fatal'), "\n";
Run Code Online (Sandbox Code Playgroud)

问题是%type_sub中的子程序似乎不接受参数.在上面的例子中,第一个print语句输出,-1而第二个输出:

Use of uninitialized value $value in string eq at (eval 15) line 1.
Use of uninitialized value $_ in string eq at (eval 15) line 1.
Can't call method "any" without a package or object reference at 
(eval 15) line 1.
Run Code Online (Sandbox Code Playgroud)

这根本不是我所期望的,但子程序正在被调用.

我究竟做错了什么?

编辑:我很草率,现在一切正常.感谢弗里多.

bri*_*foy 5

不要在配置中编写代码.使用代码创建一个库,并简单地配置要使用的子例程名称.这应该可以节省大量的工作,将字符串转换为代码并管理流程.当有人调整配置并引入语法错误时,它还可以节省大量时间来跟踪问题.

我在Mastering Perl的"配置"章节以及动态子例程的章节中详细讨论了这一点.

代码不属于配置.说,直到你相信它.