Stream vs Vistas vs Iteradores

136

¿Cuáles son las diferencias entre Streams, Views (SeqView) e Iterators en scala? Este es mi entendimiento:

  • Son todas listas perezosas.
  • Las secuencias almacenan en caché los valores.
  • ¿Los iteradores solo se pueden usar una vez? ¿No puede volver al principio y evaluar el valor nuevamente?
  • Los valores de la vista no se almacenan en caché, pero puede evaluarlos una y otra vez.

Entonces, si quiero ahorrar espacio en el montón, ¿debo usar iteradores (si no voy a recorrer la lista nuevamente) o vistas? Gracias.

JWC
fuente
77
He respondido esto antes, pero ¿cómo encontrarlo? suspiro ...
Daniel C. Sobral

Respuestas:

182

Primero, todos son no estrictos . Eso tiene un significado matemático particular relacionado con las funciones, pero, básicamente, significa que se calculan a pedido en lugar de por adelantado.

Streames una lista perezosa de hecho. De hecho, en Scala, a Streames un Listcuyo tailes a lazy val. Una vez calculado, un valor permanece calculado y se reutiliza. O, como usted dice, los valores se almacenan en caché.

Un Iteratorsolo se puede usar una vez porque es un puntero transversal a una colección, y no una colección en sí misma. Lo que lo hace especial en Scala es el hecho de que se puede aplicar la transformación como mapy filtery simplemente obtener una nueva Iteratorque sólo se aplicarán estas transformaciones cuando se pide el siguiente elemento.

Scala solía proporcionar iteradores que podrían restablecerse, pero eso es muy difícil de soportar de manera general, y no hicieron la versión 2.8.0.

Las vistas están destinadas a ser vistas como una vista de base de datos. Es una serie de transformación que se aplica a una colección para producir una colección "virtual". Como dijiste, todas las transformaciones se vuelven a aplicar cada vez que necesitas extraer elementos de él.

Ambos Iteratory las vistas tienen excelentes características de memoria. Streames agradable, pero, en Scala, su principal beneficio es escribir secuencias infinitas (particularmente secuencias definidas recursivamente). Sin embargo, se puede evitar mantener todo Streamen la memoria, asegurándose de no mantener una referencia a su head(por ejemplo, al usar en deflugar de valpara definir el Stream).

Debido a las penalizaciones incurridas por las vistas, generalmente forcese debe aplicar después de aplicar las transformaciones, o mantenerlo como una vista si se espera que solo se recuperen pocos elementos, en comparación con el tamaño total de la vista.

Daniel C. Sobral
fuente
10
IteratorTambién es bastante útil para sondear el infinito, y generalmente los prefiero a las transmisiones siempre que sea posible. El beneficio real en las secuencias es que los valores a los que se accedió anteriormente se almacenan en caché, lo que es una gran ayuda cuando se trata de implementar algo como la secuencia de Fibonacci, que se define en términos de valores anteriores.
Kevin Wright
55
Fibonacci es un ejemplo menos que perfecto, ya que solo necesita los últimos 2 valores anteriores, y mantener todo el flujo es un desperdicio. La función de Ackermann es probablemente el ejemplo canónico.
Jürgen Strobel
44
@ JürgenStrobel Ackermann daría como resultado un rendimiento pésimo, ya que el acceso indexado de las secuencias es O (n). Pero estoy de acuerdo wrt fibonacci.
Daniel C. Sobral
9
Correcto. Esto hace que Stream sea una mala elección para cualquier enfoque de almacenamiento en caché.
Jürgen Strobel
77
Esta respuesta es súper clara, debería ser parte de la documentación ... ¡oh, en realidad lo es! Gracias Daniel docs.scala-lang.org/tutorials/FAQ/stream-view-iterator.html
Svend