Comment puis-je déterminer si une fonction Perl existe à l'exécution?

Je travaille sur un framework de test en Perl. Dans le cadre des tests, je peux avoir besoin d'ajouter des vérifications préalables ou postcondition pour un test donné, mais pas nécessairement pour tous. Ce que j'ai jusqu'à présent est quelque chose comme:

eval "&verify_precondition_TEST$n";
print $@ if $@;

Malheureusement, cela génère "Undefined subroutine & verify_precondition_TEST1 appelé à ..."si la fonction n'existe pas.

Comment puis-je déterminer à l'avance si la fonction existe, avant d'essayer de l'appeler?

21
demandé sur brian d foy 2009-01-12 00:28:42

4 réponses

Avec défini:

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, j'ai seulement pensé à eval tel qu'il était dans la question mais avec des références symboliques soulevées avec Leon Timmermans, ne pourriez-vous pas faire

if (defined(&{"verify_precondition_TEST$n"}) {
    &{"verify_precondition_TEST$n"};
    print $@ if $@;
}
else {
    print "verify_precondition_TEST$n does not exist\n";
}

Même avec strict?

9
répondu Timo Metsälä 2012-04-26 22:01:08
Package::Name->can('function')

Ou

*Package::Name::function{CODE}

# or no strict; *{ "Package::Name::$function" }{CODE}

, Ou tout simplement vivre avec l'exception. Si vous appelez la fonction dans un eval et que $@ est défini, vous ne pouvez pas appeler la fonction.

Enfin, il semble que vous souhaitiez tester:: Class au lieu de l'écrire vous-même.

Edit: defined &function_name (ou no strict; defined &{ $function_name } variante), comme mentionné dans les autres réponses, semble être le meilleur moyen. UNIVERSAL:: can est le meilleur pour quelque chose que vous allez appeler comme une méthode (stylistiquement), et pourquoi déranger avec la table de symboles lorsque Perl vous donne la syntaxe pour faire ce que vous voulez.

Apprentissage++ :)

34
répondu jrockway 2009-01-12 01:52:04
sub function_exists {    
    no strict 'refs';
    my $funcname = shift;
    return \&{$funcname} if defined &{$funcname};
    return;
}

if (my $subref = function_exists("verify_precondition_TEST$n") {
    ...
}
16
répondu Leon Timmermans 2009-01-13 16:00:09

J'avais utilisé L'approche de Leon, mais quand j'avais plusieurs paquets, ça a échoué. Je ne sais pas précisément pourquoi; je pense que cela concerne la propagation de la portée entre les espaces de noms. C'est la solution que j'ai trouvé.

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});

Références:
__PACKAGE _ _ référence sur la page perlmod.

Packages / __PACKAGE _ _ référence sur la formation Perl Australie.

5
répondu Paul Nathan 2009-08-04 17:58:40