我想在调用之前检查子程序是否存在。例如:
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";
}
}
这很好,但是知道为什么第一个代码不起作用会很好吗?
答案 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";
}
}