J'ai regardé cette question mais je ne comprends toujours pas la différence entre les traits Iterable et Traversable. Quelqu'un peut-il expliquer?
J'ai regardé cette question mais je ne comprends toujours pas la différence entre les traits Iterable et Traversable. Quelqu'un peut-il expliquer?
Réponses:
Pour faire simple, les itérateurs conservent l'état, les traversables non.
A Traversablea une méthode abstraite: foreach. Lorsque vous appelez foreach, la collection alimentera la fonction passée tous les éléments qu'elle conserve, l'un après l'autre.
D'autre part, an Iterablea comme méthode abstraite iterator, qui retourne un Iterator. Vous pouvez faire appel nextà un Iteratorpour obtenir l'élément suivant au moment de votre choix. Jusqu'à ce que vous le fassiez, il doit garder une trace de l'endroit où il se trouvait dans la collection et de la suite.
Iterables'étend Traversable, donc je suppose que vous voulez dire Traversables qui ne sont pas Iterables.
Traversableinterface ne nécessite pas de garder l'état, alors que se conformer à l' Iteratorinterface le fait.
TraversableLes s qui Iterablene conservent aucun état d'itération. C'est le Iteratorcréé et retourné par le Iterablequi garde l'état.
Pensez-y comme la différence entre souffler et sucer.
Lorsque vous appelez un Traversables foreach, ou ses méthodes dérivées, il insuffle ses valeurs dans votre fonction une à la fois - il a donc le contrôle sur l'itération.
Avec le Iteratorretourné par un Iterablecependant, vous en aspirez les valeurs, en contrôlant vous-même le moment de passer à la suivante.
tl; dr Iterables sont Traversablesqui peuvent produire avec étatIterators
Premièrement, sachez que Iterablec'est un sous-portrait de Traversable.
Seconde,
Traversablenécessite l'implémentation de la foreachméthode, qui est utilisée par tout le reste.
Iterablenécessite l'implémentation de la iteratorméthode, qui est utilisée par tout le reste.
Par exemple, l'implémentation de findfor Traversableuses foreach(via un for comprehension) et lève une BreakControlexception pour arrêter l'itération une fois qu'un élément satisfaisant a été trouvé.
trait TravserableLike {
def find(p: A => Boolean): Option[A] = {
var result: Option[A] = None
breakable {
for (x <- this)
if (p(x)) { result = Some(x); break }
}
result
}
}
En revanche, la Iterablesoustraction remplace cette implémentation et appelle findle Iterator, qui arrête simplement d'itérer une fois l'élément trouvé:
trait Iterable {
override /*TraversableLike*/ def find(p: A => Boolean): Option[A] =
iterator.find(p)
}
trait Iterator {
def find(p: A => Boolean): Option[A] = {
var res: Option[A] = None
while (res.isEmpty && hasNext) {
val e = next()
if (p(e)) res = Some(e)
}
res
}
}
Ce serait bien de ne pas lancer d'exceptions pour l' Traversableitération, mais c'est la seule façon d'itérer partiellement en utilisant juste foreach.
D'un point de vue, Iterablec'est le trait le plus exigeant / puissant, car vous pouvez facilement implémenter l' foreachutilisation iterator, mais vous ne pouvez pas vraiment implémenter l' iteratorutilisation foreach.
En résumé, Iterablefournit un moyen de suspendre, de reprendre ou d'arrêter l'itération via un état Iterator. Avec Traversable, c'est tout ou rien (sans exceptions pour le contrôle de flux).
La plupart du temps, cela n'a pas d'importance et vous voudrez une interface plus générale. Mais si jamais vous avez besoin d'un contrôle plus personnalisé sur l'itération, vous aurez besoin d'un Iterator, que vous pouvez récupérer à partir d'un fichier Iterable.
La réponse de Daniel sonne bien. Voyons si je peux le dire avec mes propres mots.
Ainsi, un Iterable peut vous donner un itérateur, qui vous permet de parcourir les éléments un à la fois (en utilisant next ()), et de s'arrêter et de partir à votre guise. Pour ce faire, l'itérateur doit garder un "pointeur" interne sur la position de l'élément. Mais un Traversable vous donne la méthode, foreach, pour traverser tous les éléments à la fois sans s'arrêter.
Quelque chose comme Range (1, 10) n'a besoin que de 2 entiers comme état comme Traversable. Mais Range (1, 10) en tant que Iterable vous donne un itérateur qui doit utiliser 3 entiers pour l'état, dont l'un est un index.
Considérant que Traversable propose également foldLeft, foldRight, son foreach doit traverser les éléments dans un ordre connu et fixe. Il est donc possible d'implémenter un itérateur pour un Traversable. Par exemple, def iterator = toList.iterator
Traversabledans Scala 2.13 (il est toujours conservé comme alias obsolèteIterablejusqu'à 2.14)