6
votes

Quel est le but de la classe d'énumérateur dans Ruby

Si je crée un énuméreur comme SO:

enum.each { |i| puts i }


1 commentaires

Cet article montre quelques exemples d'utilisateurs d'énumérateurs pour une évaluation paresseuse.


5 Réponses :


4
votes

Que se passe-t-il si vous faites Enum = [1,2,3]. Enum.next Code> ?:

enum = [1,2,3].each
=> #<Enumerator: [1, 2, 3]:each>
enum.next
=> 1
enum.next
=> 2
enum.next
=> 3
enum.next
StopIteration: iteration reached an end


0 commentaires

1
votes

Je pense que le but principal est d'obtenir des éléments par demande au lieu de les obtenir tout en une seule boucle. Je veux dire quelque chose comme ceci: xxx

Notez que ces font des trucs peuvent être dans différentes fonctions bien éloignées les unes des autres.

paresseux Évalué des séquences infinies (par exemple des primes, des nombres Fibonacci, des clés de chaîne comme 'A' '..' Z ',' AA ',' Az ',' Ba ',' ZZ ',' AAA '.. etc.) sont un bon étui d'utilisation pour les énumérateurs.


0 commentaires

0
votes

Il est possible de combiner des énumérateurs: xxx


0 commentaires

1
votes

Comme répondu jusqu'à présent, l'énumérateur est utile lorsque vous souhaitez itérayer une séquence de données de longueur potentiellement infinie.

Prendre un générateur de nombres premiers prime_generator qui étend l'énumérateur par exemple. Si nous voulons obtenir les 5 premiers premiers premiers, nous pouvons simplement écrire prime_generator.take 5 au lieu d'intégrer la "limite" dans la logique génératrice. Ainsi, nous pouvons séparer des nombres premiers générateurs et prendre une certaine quantité de nombres premiers générés, rendant le générateur réutilisable.

i pour une méthode similaire en utilisant des méthodes d'énumérateur de retour énumérant comme l'exemple suivant (il peut ne pas être un "but" mais je veux simplement signaler un aspect esthétique de celui-ci): xxx

ici the prime_generator est une instance d'énumérateur qui retourne nombie un par un. Nous pouvons prendre des nombres premiers ci-dessous n à l'aide de Take_whIe méthode d'énumérable. Les méthodes chaque_cons et Find_All Les deux renvoient énumérateur afin qu'ils puissent être enchaînés. Cet exemple est destiné à générer des nombres premiers à double ci-dessous n . Cela peut ne pas être une implémentation efficace mais est facilement écrite dans une ligne et un IMHO adapté au prototypage.

Voici une implémentation assez simple de prime_generator en fonction de l'énumérateur: xxx


0 commentaires

0
votes

Pour comprendre l'avantage majeur de la classe d'énumérateur, vous devez d'abord distinguer les itérateurs internes et externes. Avec des itérateurs internes, l'itérateur lui-même contrôle l'itération. Avec des itérateurs externes, le client (souvent le programmeur) contrôle l'itération. Les clients qui utilisent un itérateur externe doivent avancer la traversée et demander explicitement l'élément suivant de l'itérateur. En revanche, le client entretient une itératrice interne une opération à effectuer et l'itérateur applique cette opération à chaque élément de la collection.

In Ruby, la classe Enumerator vous permet d'utiliser des itérateurs externes. Et une fois que vous comprenez des itérateurs externes, vous commencerez à découvrir de nombreux avantages. Premièrement, examinons la manière dont la classe d'énumérateur facilite l'itération externe: p> xxx pré>

Il est important de noter que l'appelant à un objet et qui transmettait un symbole qui correspond à une méthode instancera de la classe Enumerator Et dans notre exemple, la variable locale Enum détient une instance d'énumérateur. Et puis nous utilisons une itération externe pour traverser la méthode d'énumération que nous avons créée. Notre méthode d'énumération appelée "types" et notification que nous utilisons la méthode de rendement que nous faisons généralement avec des blocs. Ici, l'énumérateur donnera une valeur à la fois. Cela fait une pause après chaque rendement. Lorsqu'on lui a demandé une autre valeur, elle reprendra immédiatement après la dernière valeur donnée et exécutera jusqu'à la valeur suivante. Lorsque rien ne reste à céder et que vous appelez ensuite, il invoquera une exception d'excéditée. P>

Alors, quel est le pouvoir de l'itération externe à Ruby? Il y a plusieurs avantages et je soulignerai quelques-uns d'entre eux. Premièrement, la classe d'énumérateur permet une chaînage. Par exemple, with_index est défini dans la classe Enumerator et nous permet de spécifier une valeur de démarrage pour l'itération lors de l'itération sur un objet énumérateur: p> xxx pré> p> second, il fournit une tonne de Méthodes de commodité utiles à partir du module énumérable. N'oubliez pas que l'énumérateur est une classe et enuméreuse est un module, mais le module énumérable est inclus dans la classe d'énumérateur et que les énumérateurs sont énumérables: p> xxx pré>

et il y a un autre avantage majeur de Énumérateur qui pourrait ne pas être immédiatement clair. Permettez-moi d'expliquer cela à travers une démonstration. Comme vous le savez probablement, vous pouvez utiliser l'une de vos classes définies par l'utilisateur enumérables en incluant le module énumérable et définir une méthode d'instance: P>

class Fruit
  include Enumerable

  attr_accessor :kinds

  def initialize
    @kinds = %w(apple orange pear banana)
  end

  def each
    return enum_for(:each) unless block_given?
    @kinds.each { |kind| yield kind }
  end
end

f = Fruit.new
f.each
 => #<Enumerator: #<Fruit:0x007ff70aa3b548 @kinds=["apple", "orange", "pear", "banana"]>:each> 


0 commentaires