J'ai récemment découvert les blocs et fonctionnalités de Ruby, et je me demandais: quelle est sa place en termes de théorie informatique? Est-ce une technique de programmation fonctionnelle ou quelque chose de plus spécifique?
Réponses
Trop de publicités?Ruby yield
n'est pas un itérateur comme en C# et Python. yield
lui-même est en fait vraiment un concept simple, une fois que vous comprenez comment les blocs de travail en Ruby.
Oui, les blocs sont une fonctionnelle de la programmation, même si Ruby n'est pas correctement un langage fonctionnel. En fait, Ruby utilise la méthode lambda
de bloc de créer des objets, qui est emprunté à Lisp de la syntaxe pour la création de fonctions anonymes - qui est-ce qui bloque. À partir d'un ordinateur point de vue de la science, de Rubis blocs (et Lisp du lambda fonctions) sont des fermetures. En Ruby, les méthodes normalement être d'un seul bloc. (Vous pouvez passer plus, mais c'est maladroit.)
L' yield
mot-clé en Ruby, c'est juste une façon d'appeler un bloc qui a été donné à une méthode. Ces deux exemples suivants sont équivalents:
def with_log
output = yield # We're calling our block here with yield
puts "Returned value is #{output}"
end
def with_log(&stuff_to_do) # the & tells Ruby to convert into
# an object without calling lambda
output = stuff_to_do.call # We're explicitly calling the block here
puts "Returned value is #{output}"
end
Dans le premier cas, nous sommes juste en supposant que il y a un bloc et que dire de l'appeler. Dans l'autre, Ruby enveloppe le bloc dans un objet et lui passe en argument. Le premier est plus efficace et plus lisible, mais ils sont en fait la même. Vous souhaitez appeler soit une comme ceci:
with_log do
a = 5
other_num = gets.to_i
@my_var = a + other_num
end
Et il serait d'imprimer la valeur de la plaie jusqu'à obtenir attribué @my_var
. (OK, donc c'est tout à fait stupide, mais je pense que vous obtenez l'idée.)
Les blocs sont utilisés pour beaucoup de choses en Ruby. Presque tous les lieux que vous souhaitez utiliser une boucle dans un langage comme Java, il est remplacé en Ruby avec des méthodes qui prennent des blocs. Par exemple,
[1,2,3].each {|value| print value} # prints "123"
[1,2,3].map {|value| 2**value} # returns [2, 4, 8]
[1,2,3].reject {|value| value % 2 == 0} # returns [1, 3]
Comme Andrew noté, il est également couramment utilisé pour l'ouverture de fichiers et de nombreux autres endroits. Fondamentalement, lorsque vous avez une fonction standard qui pourrait utiliser une certaine logique personnalisée (comme le tri d'un tableau ou le traitement d'un fichier), vous devez utiliser un bloc. Il y a d'autres utilisations aussi, mais cette réponse est déjà si longtemps j'ai peur que cela cause des crises cardiaques chez les lecteurs les plus faibles constitutions. J'espère que cela éclaircit la confusion sur ce sujet.
Il n'y a plus de rendement et de blocs qu'une simple boucle.
La série de l'Énumération énumérable a une série de choses que vous pouvez faire avec les énumérations, en demandant par exemple si un énoncé est vrai pour tout membre d'un groupe, ou si c'est vrai pour tous les membres, ou de la recherche de l'un quelconque ou de tous les membres de la réunion de certaines conditions.
Les blocs sont également utiles pour la portée des variables. Plutôt que de se contenter de pratique, il peut aider avec un bon design. Par exemple, le code
File.open("filename", "w") do |f|
f.puts "text"
end
s'assure que le fichier de flux est fermé lorsque vous avez fini avec elle, même si une exception se produit, et que la variable est hors de portée une fois que vous avez fini avec elle.
Une casual google n'est pas venu avec un bon billet de blog sur les blocs et les rendements en ruby. Je ne sais pas pourquoi.
Réponse au commentaire:
Je soupçonne qu'il se ferme en raison de la fin du bloc, non pas parce que la variable est hors de portée.
Ma compréhension est que rien de spécial n'arrive lors de la dernière variable pointant vers un objet est hors de portée, en dehors de cet objet d'être admissible pour la collecte des ordures. Je ne sais pas comment faire pour en avoir la confirmation, si.
Je peux montrer que l'objet de fichier se ferme avant que l'on arrive à ordures collectées, ce qui habituellement ne se produit pas immédiatement. Dans l'exemple suivant, vous pouvez voir qu'un objet de fichier est fermé dans le deuxième puts
déclaration, mais il n'a pas été nettoyée.
g = nil
File.open("/dev/null") do |f|
puts f.inspect # #<File:/dev/null>
puts f.object_id # Some number like 70233884832420
g = f
end
puts g.inspect # #<File:/dev/null (closed)>
puts g.object_id # The exact same number as the one printed out above,
# indicating that g points to the exact same object that f pointed to
Je pense que la déclaration yield
provient du langage CLU . Je me demande toujours si le personnage de Tron a été nommé d'après CLU aussi ....
Je pense que "coroutine" est le mot clé que vous recherchez.
Par exemple, http://en.wikipedia.org/wiki/Yield
Rendement en informatique et en informatique:
- en informatique, le point de retour (et de rentrée) d'une coroutine