À l'aide de "retour" dans un bloc Ruby
Je suis en train d'utiliser Ruby 1.9.1 pour un langage de script incorporé, de sorte que "l'utilisateur final" le code est écrit en Ruby bloc. Un problème, c'est que je voudrais que les utilisateurs soient en mesure d'utiliser le "retour" de mots clés dans les blocs, ils n'ont pas besoin de s'inquiéter à propos de rendement implicite des valeurs. Avec cela à l'esprit, c'est le genre de chose que j'aimerais être capable de faire:
def thing(*args, &block)
value = block.call
puts "value=#{value}"
end
thing {
return 6 * 7
}
Si j'utilise le 'retour' dans l'exemple ci-dessus, j'obtiens un LocalJumpError. Je suis conscient que c'est parce que le bloc en question est un Proc et pas un lambda. Le code fonctionne, si je retire le 'retour', mais je préfère vraiment être en mesure d'utiliser le 'retour' dans ce scénario. Est-ce possible? J'ai essayé de convertir le bloc à un lambda, mais le résultat est le même.
- pourquoi voulez-vous éviter un rendement implicite de la valeur?
- J'ai une question connexe ici - stackoverflow.com/questions/25953519/... .
Vous devez vous connecter pour publier un commentaire.
Simplement utiliser
next
dans ce contexte:return
renvoie toujours à partir de la méthode, mais si vous testez ce code de la cisr vous n'avez pas de méthode, c'est pourquoi vous avezLocalJumpError
break
retourne la valeur de la bloquer et se termine à son appel. Si votre bloc a été appelé paryield
ou.call
, puisbreak
des pauses de cet itérateur tropnext
retourne la valeur de la bloquer et se termine à son appel. Si votre bloc a été appelé paryield
ou.call
, puisnext
retourne la valeur de la ligne oùyield
a été appeléVous ne pouvez pas le faire en Ruby.
La
return
mot-clé toujours retours de la méthode ou lambda dans le contexte actuel. Dans les blocs, il sera de retour à partir de la méthode de fermeture a été défini. Il ne peut pas être fait renvoyer de la appel méthode ou lambda.La Rubyspec démontre que c'est en effet le bon comportement pour Ruby (certes pas une réelle mise en œuvre, mais le but de la pleine compatibilité avec C Ruby):
Vous êtes à la recherche à partir du mauvais point de vue.
C'est une question de
thing
, pas le lambda.Où est chose invoquée? Êtes-vous à l'intérieur d'une classe?
Vous pouvez envisager d'utiliser quelque chose comme ceci:
Je crois que c'est la bonne réponse, malgré les inconvénients:
Ce hack permet aux utilisateurs d'utiliser le retour dans leur procs sans conséquences, l'autonomie est préservée, etc.
L'avantage de l'utilisation de Thread ici est que, dans certains cas, vous n'obtiendrez pas le LocalJumpError - et le retour se fera dans la place la plus inattendue (en jeu d'une méthode de niveau supérieur, de façon inattendue en ignorant le reste de son corps).
Le principal inconvénient est le risque de surcharge (vous pouvez remplacer le Fil+de jointure avec juste la
yield
si ce n'est assez de votre scénario).J'ai eu le même problème l'écriture d'un DSL pour un framework web en ruby... (le framework web Anorexique sera rock!)...
de toute façon, j'ai creusé le rubis internes et trouvé une solution simple à l'aide de la LocalJumpError retourné quand un Proc appels de retour... il fonctionne bien dans les tests jusqu'à présent, mais je ne suis pas sûr que c'est plein de preuve:
l'instruction if dans le segment du sauvetage pourrait probablement ressembler à quelque chose comme ceci:
mais c'est un territoire inexploré pour moi, donc je vais m'en tenir à ce que j'ai testé jusqu'à présent.
J'ai trouvé un moyen, mais il implique la définition d'une méthode comme une étape intermédiaire: