Как я могу определить, существует ли функция Perl во время выполнения?
Я работаю над тестовым фреймворком в Perl. В качестве части тестов мне может потребоваться добавить проверки предварительных условий или постусловий для любого данного теста, но не обязательно для всех из них. То, что у меня есть до сих пор, это что-то вроде:
eval "&verify_precondition_TEST$n";
print $@ if $@;
К сожалению, это выводит " неопределенную подпрограмму &verify_precondition_TEST1, вызванную at ...- если функция не существует.
Как я могу заранее определить, существует ли функция, прежде чем пытаться ее вызвать?
4 ответа:
С определенными:
if (eval "defined(&verify_precondition_TEST$n)") { eval "&verify_precondition_TEST$n"; print $@ if $@; } else { print "verify_precondition_TEST$n does not exist\n"; }
EDIT: Хм, я думал только об эвале, как это было в вопросе, но с символическими ссылками, поднятыми с Леоном Тиммермансом, не могли бы вы сделать
if (defined(&{"verify_precondition_TEST$n"}) { &{"verify_precondition_TEST$n"}; print $@ if $@; } else { print "verify_precondition_TEST$n does not exist\n"; }
Даже со строгим?
Package::Name->can('function')
Или
*Package::Name::function{CODE} # or no strict; *{ "Package::Name::$function" }{CODE}
Или просто жить с исключением. Если вы вызываете функцию в eval и $@ установлен, то вы не можете вызвать функцию.
Наконец, похоже, что вам может понадобиться Test:: Class вместо того, чтобы писать это самостоятельно.
Edit:
defined &function_name
(или Вариантno strict; defined &{ $function_name }
), Как упоминалось в других ответах, выглядит наилучшим образом. Универсальный:: can лучше всего подходит для того, что вы собираетесь назвать методом (стилистически), и зачем возиться с таблицей символов когда Perl дает вам синтаксис, чтобы делать то, что вы хотите.Learning++ :)
sub function_exists { no strict 'refs'; my $funcname = shift; return \&{$funcname} if defined &{$funcname}; return; } if (my $subref = function_exists("verify_precondition_TEST$n") { ... }
Я использовал подход Леона, но когда у меня было несколько пакетов, он не сработал. Я не знаю точно, почему; я думаю, что это связано с распространением области между пространствами имен. Вот решение, которое я придумал.
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});
Ссылки:
__пакет__ ссылка на страницу perlmod.Packages / _ _ PACKAGE _ _ ссылка на Perl Training Australia.