【问题标题】:How can I pass parameters to Perl subroutines defined using eval?如何将参数传递给使用 eval 定义的 Perl 子例程?
【发布时间】:2010-01-19 15:25:47
【问题描述】:

我正在使用配置文件(在 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每个类型定义,扔进一个hash,然后调用验证配置数据(下面是示意图,方便理解):

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

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

我做错了什么?

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

【问题讨论】:

    标签: perl parameters eval subroutine


    【解决方案1】:

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

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

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

    【讨论】:

    • 你当然是对的,但我认为单行不是什么大问题(反正我已经违反了这个原则)。
    • 另一个问题是如果不关闭严格的引用我不知道该怎么做。
    【解决方案2】:

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

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

    any( sub { $value eq $_ }, qw(fatal keep merge non-fatal replace) );
    

    【讨论】:

    • 哇。我一直将@_ 与移位或列表分配一起使用,而 $_ 如此常见,我完全忘记了它不是自动设置的。
    • 我刚刚尝试了您的“任何”解决方案,但没有运气。这里有一个更一般的问题,即如何使用 eval 或其他方法定义带有字符串的子例程。也许我稍后会问。
    • 我修好了。 List::MoreUtils 默认不导出任何东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-22
    • 2021-03-09
    • 2019-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-24
    相关资源
    最近更新 更多