Comment puis-je élégamment appeler un sous-programme Perl dont le nom est tenu dans une variable?
Je garde le nom de la sous-routine, je tiens à appeler à l'exécution dans une variable appelée $l'action. Puis-je l'utiliser pour l'appel de sous au bon moment:
&{\&{$action}}();
Fonctionne très bien. La seule chose que je n'aime pas, c'est que c'est laid, et à chaque fois que je le fais, je me sens redevable à ajouter un commentaire pour la prochaine développeur:
# call the sub by the name of $action
Quelqu'un connais une jolie façon de faire cela?
Mise à JOUR: L'idée ici était d'éviter d'avoir à maintenir un envoi de la table chaque fois, j'ai ajouté un nouveau appelable sous, depuis que je suis le seul développeur, je ne suis pas inquiet au sujet d'autres programmeurs suit ou ne suit pas les "règles". Sacrifier un peu de sécurité pour mon confort. Au lieu de mon expédition module de vérification de $action pour s'assurer que 1) c'est le nom d'une sous-routine et de ne pas l'exécution de code malveillant avec eval, et 2) qu'il ne serait pas exécuter n'importe quel sous préfacé par un trait de soulignement, qui devrait être marquée comme interne uniquement des sous-marins par cette convention de nommage.
Toute réflexion sur cette approche? Une liste blanche des sous-programmes dans l'envoi de la table est quelque chose que j'oublierai tout le temps, et mes clients serait plutôt me pencher du côté de "ça marche" que "c'est presque sûr". (très peu de temps pour développer des applications)
Dernière mise à JOUR: je pense que j'ai décidé sur un envoi de la table, après tout. Bien que je serais curieux de savoir si quelqu'un qui lit cette question n'a jamais essayé de les faire disparaître, et comment ils l'ont fait, j'ai à vous incliner devant la sagesse collective ici. Merci à tous, beaucoup de grandes réponses.
- Réaliser que lorsque vous prenez une référence à quelque chose d'immédiatement déréférencement d'elle, vous pouvez sauter le moyen étapes de. 🙂
- généralement (et certainement dans ce cas), mais voir stackoverflow.com/questions/1836178/... pour un contre-exemple. 🙂
- Une expédition table signifie également que vous pouvez
use strict
, qui est généralement une bonne chose.
Vous devez vous connecter pour publier un commentaire.
Plutôt que de stocker les noms de sous-routine dans une variable et en les appelant, une meilleure façon de le faire est d'utiliser une table de hachage de sous-routine références (autrement connu comme un expédition table.)
Ensuite, vous pouvez appeler le droit que l'on puisse facilement:
Vous pouvez également ajouter un peu de vérification pour vous assurer que
$action
est une clé valide dans la table de hachage, et ainsi de suite.En général, vous devriez éviter de références symboliques (ce que vous faites maintenant) car elles causent toutes sortes de problèmes. En outre, en utilisant de vrais sous-routine les références à travailler avec
strict
allumé.$actions{$action}->($parmVariable,11,'a');
Les paramètres devront être cohérents à travers tous les sous-routines d'être appelé, bien que les valeurs peuvent venir à partir de variables de cours.Juste
&$action()
, mais en général c'est plus agréable à utiliser coderefs depuis le début, ou l'utilisation d'un répartiteur de hachage. Par exemple:strict
activé, ce qui est un autre avantage de faire de cette façon.use strict qw(vars subs)
est un moyen plus court de direuse strict; no strict 'refs';
Hein? Vous pouvez juste dire
Exemple:
Des Constructions comme
aussi de travail.
use strict
(et bien sûr, vous le faites), vous aurez besoin de direno strict 'refs'
ou tout simplementuse strict qw(vars subs)
pour utiliser cette syntaxe.Je ne suis pas sûr que je comprends ce que tu veux. (Je pense que c'est un autre dans un récent groupe de "Comment puis-je utiliser une variable comme nom de variable?", questions, mais peut-être pas.)
Dans tous les cas, vous devriez être en mesure d'attribuer un ensemble de sous-routine à une variable (comme référence), puis l'appeler simplement:
La chose la plus importante est: pourquoi voulez-vous utiliser une variable comme nom de fonction. Ce qui va se passer si il sera 'eval'?
S'il existe une liste de fonctions qui peuvent être utilisées? Ou peut-il être n'importe quelle fonction? Si la liste existe - combien de temps il est?
Généralement, la meilleure façon de gérer de tels cas est d'utiliser l'expédition de tables:
Et puis juste:
Pour plus d'info sur pouvez(): http://perldoc.perl.org/UNIVERSAL.html
- Je faire quelque chose de similaire. Je l'ai divisée en deux lignes pour les rendre un peu plus visible, mais ce n'est pas beaucoup plus jolie.
Je ne sais pas de plus juste ou la plus jolie façon de faire. Pour ce que ça vaut, nous avons la production de code qui fait ce que vous faites, et il fonctionne sans avoir à désactiver
use strict
.$sub->($parmVariable,11,'a');
Chaque paquet de Perl est déjà une table de hachage. Vous pouvez ajouter des éléments et de les référencer par les opérations de hachage. En général, il n'est pas nécessaire de dupliquer les fonctionnalités supplémentaires de la table de hachage.
Le code imprime:
Si vous avez besoin d'un nom distinct de l'espace, vous pouvez définir un kit dédié.
Voir perlmod pour de plus amples informations.
Utiliser
Ou utiliser la fonction eval pour exécuter la fonction:
Je l'ai fait de cette façon:
Si c'est uniquement dans un programme, écrire une fonction qui s'appelle un sous-programme à l'aide d'un nom de variable, et ont seulement le document it/excuse une fois?
J'ai utilisé ceci: il fonctionne pour moi.
Ou vous pouvez utiliser "faire", assez similaire avec les messages précédents: