Как определить, существует ли функция Perl во время выполнения?
Я работаю над тестовой платформой в Perl. В рамках тестов мне может потребоваться добавить предварительные условия или проверки условий для любого данного теста, но не обязательно для всех из них. То, что у меня есть, выглядит примерно так:
eval "&verify_precondition_TEST$n";
print [email protected] if [email protected];
К сожалению, это выводит "Undefined подпрограмма & ver_precondition_TEST1, вызываемая при...", если функция не существует.
Как я могу заранее определить, существует ли функция, прежде чем пытаться ее вызвать?
Ответы
Ответ 1
Определяется:
if (eval "defined(&verify_precondition_TEST$n)") {
eval "&verify_precondition_TEST$n";
print [email protected] if [email protected];
}
else {
print "verify_precondition_TEST$n does not exist\n";
}
РЕДАКТИРОВАТЬ: Хмм, я думал об эволюции, как в вопросе, но с символическими ссылками, поднятыми с Леон Тиммерманом, не могли бы вы сделать
if (defined(&{"verify_precondition_TEST$n"}) {
&{"verify_precondition_TEST$n"};
print [email protected] if [email protected];
}
else {
print "verify_precondition_TEST$n does not exist\n";
}
даже со строгим?
Ответ 2
Package::Name->can('function')
или
*Package::Name::function{CODE}
# or no strict; *{ "Package::Name::$function" }{CODE}
или просто жить с исключением. Если вы вызываете функцию в eval и [email protected], то вы не можете вызвать функцию.
Наконец, похоже, что вам может понадобиться Test:: Class вместо того, чтобы писать это самостоятельно.
Изменить: defined &function_name
(или вариант no strict; defined &{ $function_name }
), как указано в других ответах, выглядит наилучшим образом. UNIVERSAL:: can лучше всего подходит для чего-то, что вы собираетесь назвать методом (стилистически), и зачем беспокоиться о том, чтобы использовать таблицу символов, когда Perl дает вам синтаксис, чтобы делать то, что вы хотите.
Обучение ++:)
Ответ 3
sub function_exists {
no strict 'refs';
my $funcname = shift;
return \&{$funcname} if defined &{$funcname};
return;
}
if (my $subref = function_exists("verify_precondition_TEST$n") {
...
}
Ответ 4
Я использовал Leon подход, но когда у меня было несколько пакетов, он не удался. Я точно не знаю, почему; Я думаю, что это связано с распространением сферы действия между пространствами имен. Это решение, с которым я столкнулся.
my %symbols = ();
my $package =__PACKAGE__; #bring it in at run-time
{
no strict;
%symbols = %{$package . "::"}; #See Symbol Tables on perlmod
}
print "$funcname not defined\n" if (! defined($symbols{$funcname});
Литература:
__ PACKAGE__ ссылка на странице perlmod.
Пакеты /__ PACKAGE__ ссылка на Perl Training Australia.