【问题标题】:Non standard way of calling sub-routines in Perl在 Perl 中调用子例程的非标准方式
【发布时间】:2012-05-21 18:48:03
【问题描述】:

我正在尝试一种在 Perl 脚本中调用子例程的不同方式。

我有一组函数如下:

sub Testcase_CheckStatus {
    print "TestCase_CheckStatus called\n";
}

然后我正在使用“CheckStatus”之类的键遍历 Perl 哈希:

while (my ($k, $v) = each %test_cases) {
    print "TestCase_$k","\n";
    Testcase_$k();
}

基本上,我想在解析哈希键时像上面一样调用函数Testcase_CheckStatus,但是我收到了这个错误:

无法在 ./main.pl 第 17 行通过包“CheckStatus”定位对象方法“Testcase_”(也许您忘记加载“CheckStatus”?)

我可以做些什么来纠正这个问题?有没有其他方法可以做到这一点?

【问题讨论】:

  • 请注意,在“严格”模式下这是不允许的,这是有原因的。在运行时构建函数或变量名是危险且脆弱的。另一方面,wk 的解决方案(使用匿名函数的散列)给出了完全相同的结果,并且既安全又完全地道。
  • 重要背景阅读:“为什么使用变量作为变量名是愚蠢的”(part 1part 2part 3)作者 Mark Dominus,出色的 Higher Order Perl 的作者.

标签: perl subroutine


【解决方案1】:

其他方式:

use 5.010;
use warnings;
use strict;


my $testcases = {
    test_case_1 => sub {
        return 1 * shift();
    },
    test_case_2 => sub {
        return 3 * shift();
    },
    test_case_3 => \&SomeSub,
};

for (1 .. 3) {
    say $testcases->{ 'test_case_' . $_ }(7);
}


sub SomeSub {
    return 5 * shift();
}

【讨论】:

  • 它通常被称为“调度表”。
【解决方案2】:

以下内容应该可以让你做你想做的事:

while (my ($k, $v) = each %test_cases) {
    print "TestCase_$k","\n";
    &{"Testcase_$k"}();
}

但是,如果 strict 正在使用,这将不起作用。如果您使用strict,则需要在while 循环中使用no strict,例如:

while (my ($k, $v) = each %test_cases) {
    no strict 'refs';

    print "TestCase_$k","\n";
    &{"Testcase_$k"}();
}

【讨论】:

  • 如果程序员不小心从外部提供的数据,这是不习惯的,并且很容易出现命令注入。我不能推荐它。 - wk.的答案显示了一个调度表;大多数情况下都应该使用该解决方案。
  • no strict ... 几乎等于“让我们走错路”。我的意思是,它在许多情况下都可以用作 hack,但通常它表明正在采取错误的方法。如果你必须这样做,那就去做吧,但至少要在它周围建立一条警告护城河。
  • 你们都是对的,我自己不会这样做,但这是对 OP 的问题的直接答案,即如何在给定字符串中函数名的一部分的情况下调用函数。跨度>
  • @mttrb 这是一个直接而有用的答案,尽管它不太正确。 (关于 OP 对替代方案持开放态度。)只是我们更愿意接受另一个 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-05
  • 1970-01-01
  • 1970-01-01
  • 2016-02-29
  • 1970-01-01
相关资源
最近更新 更多