Quand est - `eval` Ruby-elle justifiée?
"Est 'eval' est supposé être méchant?" inspiré celui-ci:
Surtout tout le monde est d'accord que eval
est mauvais, et dans la plupart des cas, il est plus élégant/plus sûr de remplacement.
Donc je voulais vous demander: si eval
est utilisée à mauvais escient que, souvent, est-il vraiment besoin d'une fonctionnalité du langage? Est-il de faire plus de mal que de bien?
Personnellement, le seul endroit que je trouve très utile consiste à interpoler les chaînes fournies dans le fichier de configuration.
Edit: Le but de cette question est d'obtenir autant de cas concrets que possible lorsque eval est la seule ou la meilleure solution. Donc, s'il vous plaît, n'allez pas dans l' "si une limite de langue du programmeur de la créativité" de la direction.
Edit2: Et quand je dis eval
, bien sûr, je me réfère à eval
ing chaîne, ne passant pas par ruby bloc de instance_eval
ou class_eval
.
Vous devez vous connecter pour publier un commentaire.
Le seul cas que je connais (autre que "j'ai cette chaîne et je veux l'exécuter") est dynamiquement traiter avec des variables locales et globales. Ruby a des méthodes pour obtenir les noms des variables locales et globales, mais il manque de méthodes pour obtenir ou définir leurs valeurs sur la base de ces noms. La seule façon de le faire autant que je sache est avec
eval
.Toute autre utilisation est presque certainement faux. Je ne suis pas un gourou et ne peut pas affirmer catégoriquement qu'il n'y a pas d'autres, mais tous les autres cas d'utilisation, je n'ai jamais vu où quelqu'un a dit, "Vous avez besoin d'eval pour cela," j'ai trouvé une solution qui n'a pas.
Noter que je parle chaîne eval ici, par la manière. Ruby a également
instance_eval
, ce qui peut prendre soit une chaîne ou d'un bloc à exécuter dans le cadre du récepteur. Le bloc de la forme de cette méthode est rapide, sûr et très utile.eval
, vous pouvez abréger ce à quelque chose commeset_ivars(binding)
.eval('self', block.binding)
Proc#binding
tout à fait. Je ne suis toujours pas convaincu du bon usage de laeval
pour accéder aux variables locales.binding.receiver
(c'est peut-être une nouvelle méthode a été ajoutée depuis votre commentaire?) 🙂binding.receiver
méthode n'existait pas, alors! 🙂Quand est-il justifié? Je dirais que quand il n'y a pas d'alternative raisonnable. J'ai été en mesure de penser à une utilisation où je ne peux pas penser à une alternative: la cisr, qui, si vous creusez assez profond (à
workspace.rb
, autour de la ligne 80 dans ma copie si vous êtes intéressé) utilise eval pour l'exécution de votre entrée:Qui semble assez raisonnable pour moi une situation où vous avez spécifiquement ne sais pas quel est le code que vous allez avoir à s'exécuter jusqu'à ce que le moment où vous êtes invité à le faire. Quelque chose de dynamique et interactive semble correspondre au projet de loi.
La raison eval est là c'est parce que lorsque vous en avez besoin, quand vous en avez vraiment besoin, il n'existe pas de substituts. Il ya seulement tellement que vous pouvez faire avec la méthode de création d'expédition, après tout, et à un certain moment, vous avez besoin d'exécuter du code arbitraire.
Simplement parce qu'une langue a une fonction qui pourrait être dangereux ne signifie pas qu'il est nécessairement une mauvaise chose. Quand une langue suppose d'en savoir plus que son utilisateur, c'est quand il ya des problèmes.
Je dirais que lorsque vous trouvez un langage de programmation sans danger, vous avez trouvé un produit qui n'est pas très utile.
Quand est-eval-elle justifiée? De manière pragmatique, quand vous dites que c'est. Si c'est votre programme et vous êtes programmeur, vous pouvez définir les paramètres.
Il est très important de cas d'utilisation pour
eval()
qui ne peut pas (à ma connaissance) être réalisé en utilisant autre chose, c'est de trouver l'objet correspondant de référence pour une liaison.Disons que vous avez passé un bloc mais (pour certaines raisons) vous avez besoin d'accéder à du contexte de l'objet de la liaison, vous devez effectuer les opérations suivantes:
Il est également utile de définir les éléments suivants:
De l'OMI, surtout pour le Domaine des Langues Spécifiques.
"L'évaluation des Options en Ruby" est un article de Jay Champs à ce sujet sur InfoQ.
eval est un outil, il n'est ni intrinsèquement bon, ni mauvais. Il est justifié chaque fois que vous êtes certain que c'est le bon outil pour ce que vous essayez d'accomplir.
Un outil comme eval est au sujet de l'évaluation du code au moment de l'exécution par rapport à "compiler" le temps. Savez-vous ce que le code est lorsque vous lancez Ruby? Alors vous n'avez probablement pas besoin d'eval. Votre code est de la génération de code en cours d'exécution? alors vous avez probablement besoin de eval-il.
Par exemple, les méthodes/fonctions nécessaires à une récursif décent analyseur dépendent de la langue analysée. Si votre application crée un tel analyseur à la volée, alors il pourrait être judicieux d'utiliser la fonction eval. Vous pouvez écrire une généralisé de l'analyseur, mais il pourrait ne pas être élégant, une solution.
"En programmant de remplissage dans un letrec dans le Schéma. Les Macros ou eval?" est une question que j'ai posté sur eval dans le Schéma, où son utilisation est surtout inévitable.
eval
est presque la même, donc je ne sais pas pourquoi ce serait différent?En général
eval
est un langage utile si vous souhaitez exécuter du code arbitraire. Cela devrait être une chose rare, mais peut-être vous faire votre propre REPL ou vous souhaitez exposer le rubis au moment de l'exécution à l'utilisateur final pour une raison quelconque. Il peut arriver, et c'est pourquoi la fonctionnalité existe. Si vous l'utilisez pour contourner une partie de la langue (par exemple, des variables globales) alors soit la langue est défectueux ou de votre compréhension de la langue est erronée. La solution est généralement de ne pas utiliser la fonction eval, mais soit mieux comprendre la langue ou de choisir une autre langue.Il est intéressant de noter que dans rubis particulièrement
instance_eval
etclass_eval
avoir d'autres usages.