检查Perl中是否存在子例程

时间:2014-08-25 12:54:44

标签: perl

我想在调用之前检查子程序是否存在。例如:

use warnings;
use strict;

my @names=qw (A B);

for (@names) {
  my $sub=\&{"print$_"};
  if (exists &{$sub}) {
    &$sub();
  }
}

sub printA {
  print "hello A\n";
}

但是这段代码不起作用。它给出了错误:

Undefined subroutine &main::printB

我知道我可以使用eval

for (@names) {
  my $sub=\&{"print$_"};
  eval {
    &$sub();
  };
  if ($@) {
    print "$_ does not exist..\n";
  }
}

这很好,但是知道为什么第一个代码不起作用会很好吗?

4 个答案:

答案 0 :(得分:5)

my $sub = main->can("print$_");
if ($sub) {
  $sub->();
}

来自perldoc

  

可以检查对象或类是否有一个名为METHOD的方法。如果是,则返回对sub的引用。如果没有,则返回undef。这包括由$ obj,CLASS或VAL继承或导入的方法。

答案 1 :(得分:4)

您在尝试知道子存在之前是否尝试进行引用。首先使用exists调用中子例程的名称进行检查。

use strict;
use warnings;

foreach (qw(A B)) {
    my $name = 'print' . $_;
    if (exists &{$name}) {
        my $s = \&{$name};
        $s->();
    }
}

sub printA {
    print "hello A"
}

答案 2 :(得分:3)

如果您将代码更改为:

for (@names) {
  my $sub="print$_";
  no strict 'refs';
  if (exists &{$sub}) {
    &$sub;
  }
}

该方法仅在存在时才会调用。

答案 3 :(得分:1)

以这种方式避免按字符串调用子例程几乎肯定更好。一种简单的方法是使用子程序引用。

my %prints = (
  'printA' => \&printA,
  'printB' => \&printB,
);
for (@names) {
  my $printName = "print$_";
  if($prints{$printName}) {
    $prints{$printName}->();
  }
  else {
    warn "Invalid print: $printName";
  }
}