Si je crée un énuméreur comme SO:
enum.each { |i| puts i }
5 Réponses :
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
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: Notez que ces paresseux Évalué des séquences infinies (par exemple des primes, des nombres Fibonacci, des clés de chaîne comme font des trucs code> peuvent être dans différentes fonctions bien éloignées les unes des autres. P>
'A' '..' Z ',' AA ',' Az ',' Ba ',' ZZ ',' AAA '.. code> etc.) sont un bon étui d'utilisation pour les énumérateurs. p> p>
Il est possible de combiner des énumérateurs:
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 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): p> ici the Voici une implémentation assez simple de prime_generator code> qui étend l'énumérateur par exemple. Si nous voulons obtenir les 5 premiers premiers premiers, nous pouvons simplement écrire
prime_generator.take 5 code> 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. P>
prime_generator code> est une instance d'énumérateur qui retourne nombie un par un. Nous pouvons prendre des nombres premiers ci-dessous
n code> à l'aide de
Take_whIe code> méthode d'énumérable. Les méthodes
Find_All CODE> 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 code>. Cela peut ne pas être une implémentation efficace mais est facilement écrite dans une ligne et un IMHO adapté au prototypage. P>
prime_generator code> en fonction de l'énumérateur: P>
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> 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> 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>
Cet article montre quelques exemples d'utilisateurs d'énumérateurs pour une évaluation paresseuse.