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

发布于 2024-08-18 13:22:15 字数 1176 浏览 5 评论 0原文

我使用配置文件(在 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 中的子例程似乎不接受参数。在上面的情况下,第一个 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.

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

我做错了什么?

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

I'm using a config file (in YAML) to define types that are used later on to validate other config values required for my app:

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

The idea is to eval each type definition, throw them into a hash and then call to validate configuration data (the following is schematic for easy comprehensibility):

#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";

The problem is that the subroutines in %type_sub don't seem to accept parameters. In the above case, the first print statement outputs -1 while the second outputs:

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.

which is not at all what I expect, yet the subroutines are being called.

What am I doing wrong?

EDIT:
I was being sloppy and everything works fine now. Thanks to Friedo.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

再可℃爱ぅ一点好了 2024-08-25 13:22:15

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

我在 掌握 Perl 的“配置”章节以及有关动态的章节中广泛讨论了这一点子程序。

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

Don't write code in configuration. Create a library with the code and simply configure which subroutine name you want to use. That should save you an huge amount of work translating strings to code and managing the process. It also saves you a ton of time tracking down problems when someone adjusts the configuration and introduces a syntax error.

I talk about this extensively in the "Configuration" chapter in Mastering Perl, as well as the chapters on dynamic subroutines.

Code doesn't belong in configuration. Say that until you believe it.

情场扛把子 2024-08-25 13:22:15

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

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

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

Your subroutine parameters will be in the @_ array, not $_. To get the first parameter, look in $_[0] or do my $foo = shift;. (shift operates on @_ by default.)

As for any, I believe the problem is due to any not being able to load its prototype at runtime (subroutine prototypes can only be called at compile-time.) You may need to use explicit parens and an explicit subroutine reference:

any( sub { $value eq $_ }, qw(fatal keep merge non-fatal replace) );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文