4

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

---
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 ...

这个想法是对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";

问题是 %type_sub 中的子例程似乎不接受参数。在上述情况下,第一个打印语句输出-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.

这根本不是我所期望的,但是正在调用子例程。

我究竟做错了什么?

编辑:我很马虎,现在一切正常。感谢弗里多。

4

2 回答 2

5

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

我在Mastering Perl的“配置”一章以及关于动态子例程的章节中广泛讨论了这一点。

代码不属于配置。直到你相信为止。

于 2010-01-19T16:39:56.040 回答
3

您的子程序参数将在@_数组中,而不是$_. 要获取第一个参数,请查看$_[0]或执行my $foo = shift;. (默认shift运行@_。)

至于any,我认为问题是由于any无法在运行时加载其原型(子例程原型只能在编译时调用。)您可能需要使用显式括号和显式子例程引用:

any( sub { $value eq $_ }, qw(fatal keep merge non-fatal replace) );
于 2010-01-19T15:38:19.600 回答