Come posso determinare se esiste una funzione Perl in fase di esecuzione?
-
10-07-2019 - |
Domanda
Sto lavorando a un framework di test in Perl. Come parte dei test, potrei aver bisogno di aggiungere controlli precondizione o postcondizione per ogni dato test, ma non necessariamente per tutti. Quello che ho finora è qualcosa di simile:
eval "&verify_precondition_TEST$n";
print $@ if $@;
Sfortunatamente, questo genera " Subroutine non definita & amp; confirm_precondition_TEST1 chiamato a ... " se la funzione non esiste.
Come posso determinare in anticipo se la funzione esiste, prima di provare a chiamarla?
Soluzione
Con definito:
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: hmm, ho solo pensato a eval com'era nella domanda, ma con riferimenti simbolici sollevati con Leon Timmermans, non puoi farlo
if (defined(&{"verify_precondition_TEST$n"}) {
&{"verify_precondition_TEST$n"};
print $@ if $@;
}
else {
print "verify_precondition_TEST$n does not exist\n";
}
anche con rigoroso?
Altri suggerimenti
Package::Name->can('function')
o
*Package::Name::function{CODE}
# or no strict; *{ "Package::Name::$function" }{CODE}
o semplicemente vivere con l'eccezione. Se si chiama la funzione in un eval e $ @ è impostato, non è possibile chiamare la funzione.
Infine, sembra che potresti voler Test :: Class invece di scriverlo tu stesso.
Modifica: definito & amp; nome_funzione
(o la variante non rigorosa; definita & amp; {$ nome_funzione}
), come menzionato nelle altre risposte, sembra essere la miglior modo. UNIVERSAL :: can è la cosa migliore per qualcosa che chiamerai come metodo (stilisticamente), e perché preoccuparsi di fare casino con la tabella dei simboli quando Perl ti dà la sintassi per fare quello che vuoi.
Apprendimento ++ :)
sub function_exists {
no strict 'refs';
my $funcname = shift;
return \&{$funcname} if defined &{$funcname};
return;
}
if (my $subref = function_exists("verify_precondition_TEST$n") {
...
}
Avevo usato l'approccio di Leon, ma quando avevo più pacchetti fallì. Non sono sicuro del perché; Penso che si riferisca alla propagazione dell'ambito tra gli spazi dei nomi. Questa è la soluzione che mi è venuta in mente.
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});
Riferimenti:
__PACKAGE__ riferimento nella pagina perlmod.
Pacchetti / __ PACCHETTO__ di riferimento su Perl Training Australia.