¿Cómo puedo determinar si existe una función Perl en tiempo de ejecución?
-
10-07-2019 - |
Pregunta
Estoy trabajando en un marco de prueba en Perl. Como parte de las pruebas, es posible que deba agregar verificaciones de precondición o poscondición para cualquier prueba dada, pero no necesariamente para todas ellas. Lo que tengo hasta ahora es algo como:
eval "&verify_precondition_TEST$n";
print $@ if $@;
Desafortunadamente, esto genera " Subrutina indefinida & amp; generate_precondition_TEST1 llamado en ... " si la función no existe.
¿Cómo puedo determinar de antemano si existe la función, antes de intentar llamarla?
Solución
Con definido:
if (eval "defined(&verify_precondition_TEST$n)") {
eval "&verify_precondition_TEST$n";
print $@ if $@;
}
else {
print "verify_precondition_TEST$n does not exist\n";
}
EDITAR: hmm, solo pensé en evaluar como estaba en la pregunta, pero con referencias simbólicas planteadas con Leon Timmermans, ¿no podrías hacerlo?
if (defined(&{"verify_precondition_TEST$n"}) {
&{"verify_precondition_TEST$n"};
print $@ if $@;
}
else {
print "verify_precondition_TEST$n does not exist\n";
}
incluso con estricto?
Otros consejos
Package::Name->can('function')
o
*Package::Name::function{CODE}
# or no strict; *{ "Package::Name::$function" }{CODE}
o simplemente vive con la excepción. Si llama a la función en una evaluación y se establece $ @, entonces no puede llamar a la función.
Finalmente, parece que puede querer Test :: Class en lugar de escribir esto usted mismo.
Editar: define & amp; function_name
(o la no estricta; definida & amp; {$ function_name}
variante), como se menciona en las otras respuestas, parece ser la mejor manera. UNIVERSAL :: can es lo mejor para algo que va a llamar como método (estilísticamente), y por qué molestarse en jugar con la tabla de símbolos cuando Perl le da la sintaxis para hacer lo que quiere.
Aprendizaje ++ :)
sub function_exists {
no strict 'refs';
my $funcname = shift;
return \&{$funcname} if defined &{$funcname};
return;
}
if (my $subref = function_exists("verify_precondition_TEST$n") {
...
}
Había usado el enfoque de Leon, pero cuando tuve varios paquetes, falló. No estoy seguro exactamente por qué; Creo que se relaciona con la propagación del alcance entre espacios de nombres. Esta es la solución que se me ocurrió.
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});
Referencias:
__PACKAGE__ referencia en la página de perlmod.
Paquetes / __ PACKAGE__ referencia en Perl Training Australia.