concatenate scala scala-collections

concatenate - scala mutable collections



Scala: ¿Cuál es la diferencia entre los rasgos de Traversable y Iterable en las colecciones de Scala? (3)

Para decirlo simplemente, los iteradores mantienen el estado, los traversables no.

Un Traversable tiene un método abstracto: foreach . Cuando llame a foreach , la colección transmitirá a la función pasada todos los elementos que mantiene, uno después del otro.

Por otro lado, un iterator tiene como iterator método abstracto, que devuelve un Iterator . Puede llamar a next en un Iterator para obtener el siguiente elemento en el momento que elija. Hasta que lo haga, debe hacer un seguimiento de dónde estaba en la colección y qué es lo próximo.

He analizado esta pregunta pero todavía no entiendo la diferencia entre los rasgos Iterable y Traversable. ¿Alguien puede explicar?


Piense en ello como la diferencia entre soplar y chupar.

Cuando llame a un Traversable foreach Traversable , o sus métodos derivados, inflará sus valores en su función de uno en uno, para que tenga control sobre la iteración.

Sin embargo, con el Iterator devuelto por un Iterable , le quitas los valores, controlando cuándo pasar al siguiente tú mismo.


tl; dr Iterables son Traversables que pueden producir Iterators estado

Primero, sepa que Iterable es un atributo de Traversable .

Segundo,

  • Traversable requiere implementar el método foreach , que es utilizado por todo lo demás.

  • Iterable requiere implementar el método de iterator , que es utilizado por todo lo demás.

Por ejemplo, la implementación de find para Traversable usa foreach (a través de a para comprensión) y arroja una excepción BreakControl para detener la iteración una vez que se ha encontrado un elemento satisfactorio.

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

Por el contrario, el resta Iterable anula esta implementación y llama a find en el Iterator , que simplemente detiene la iteración una vez que se encuentra el elemento:

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

Sería bueno no lanzar excepciones para la iteración de Traversable , pero esa es la única forma de iterar parcialmente cuando se usa solo foreach .

Desde una perspectiva, Iterable es el rasgo más exigente / poderoso, ya que puede implementar fácilmente foreach utilizando iterator , pero no puede implementar iterator utilizando foreach .

En resumen, Iterable proporciona una forma de pausar, reanudar o detener la iteración a través de un Iterator estado. Con Traversable , es todo o nada (sin excepciones para el control de flujo).

La mayoría de las veces no importa, y querrás la interfaz más general. Pero si alguna vez necesita un control más personalizado sobre la iteración, necesitará un Iterator , que puede recuperar de un Iterable .