49 votes

Caractéristique de rendement de Ruby en relation avec l'informatique

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?

104voto

Chuck Points 138930

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.

6voto

Andrew Grimm Points 22996

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

2voto

Daniel Lucraft Points 3323

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 ....

0voto

Genericrich Points 3538

J'ai toujours pensé que c'était de SmallTalk. Que dites-vous? Arrgh!

0voto

Brian Points 82719

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

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