66 votes

Comment puis-je appeler de manière élégante une sous-routine Perl dont le nom est contenu dans une variable ?

Je conserve le nom de la sous-routine que je veux appeler au moment de l'exécution dans une variable appelée $action. Je l'utilise ensuite pour appeler cette sous-routine au bon moment :

&{\&{$action}}();

Fonctionne bien. La seule chose que je n'aime pas, c'est que c'est moche et qu'à chaque fois que je le fais, je me sens obligé d'ajouter un commentaire pour le prochain développeur :

# call the sub by the name of $action

Quelqu'un connaît-il un moyen plus joli de faire cela ?


MISE À JOUR : L'idée ici était d'éviter d'avoir à maintenir une table de répartition à chaque fois que j'ajoutais un nouveau sous-sujet appelable, puisque je suis le seul développeur, je ne m'inquiète pas du fait que les autres programmeurs suivent ou non les " règles ". Je sacrifie un peu de sécurité pour mon confort. Au lieu de cela, mon module de distribution vérifierait $action pour s'assurer que 1) c'est le nom d'une sous-routine définie et non du code malveillant à exécuter avec eval, et 2) qu'il n'exécuterait pas de sous-programme précédé d'un trait de soulignement, qui serait marqué comme sous-programme interne seulement par cette convention de nommage.

Que pensez-vous de cette approche ? J'oublie souvent de placer des sous-routines sur la liste blanche dans la table d'envoi, et mes clients préfèrent que je prenne le parti du "ça marche" plutôt que du "c'est méchamment sûr". (temps très limité pour développer des applications)


MISE À JOUR FINALE : Je pense que j'ai finalement opté pour une table d'expédition. Bien que je sois curieux de savoir si quelqu'un qui lit cette question a déjà essayé de s'en passer et comment il l'a fait, je dois m'incliner devant la sagesse collective ici. Merci à tous, beaucoup de bonnes réponses.

9voto

Nehal J. Wani Points 503
__PACKAGE__->can($action)->(@args);

Pour plus d'informations sur can() : http://perldoc.perl.org/UNIVERSAL.html

6voto

Wes Points 572

Je fais quelque chose de similaire. Je le divise en deux lignes pour le rendre légèrement plus identifiable, mais ce n'est pas beaucoup plus joli.

my $sub = \&{$action};
$sub->();

Je ne connais pas de manière plus correcte ou plus jolie de le faire. Pour ce que cela vaut, nous avons un code de production qui fait ce que vous faites, et cela fonctionne sans avoir à désactiver l'option use strict .

4voto

ceving Points 3990

Chaque paquet en Perl est déjà une table de hachage. Vous pouvez ajouter des éléments et les référencer par les opérations de hachage normales. En général, il n'est pas nécessaire de dupliquer la fonctionnalité par une table de hachage supplémentaire.

#! /usr/bin/perl -T
use strict;
use warnings;

my $tag = 'HTML';

*::->{$tag} = sub { print '<html>', @_, '</html>', "\n" };

HTML("body1");

*::->{$tag}("body2");

Le code s'imprime :

<html>body1</html>
<html>body2</html>

Si vous avez besoin d'un espace de nom distinct, vous pouvez définir un paquet dédié.

Ver perlmod pour de plus amples informations.

1voto

Grolim Points 1

Soit utiliser

&{\&{$action}}();

Ou utilisez eval pour exécuter la fonction :

eval("$action()");

1voto

Putnik Points 244

Je l'ai fait de cette façon :

@func = qw(cpu mem net disk);
foreach my $item (@func){
    $ret .= &$item(1);
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X