Flujo vs Vistas vs Iteradores

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

  • Son todas listas perezosas.
  • Flujos de caché de los valores.
  • Los iteradores solo pueden usarse una vez? No puede volver al principio y evaluar el valor nuevamente?
  • Los valores de View no están almacenados en la memoria 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 de nuevo) o vistas? Gracias.

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

Stream es una lista perezosa de hecho. De hecho, en Scala, un Stream es una List cuya tail es un lazy val . Una vez calculado, un valor permanece computado y se reutiliza. O, como dices, los valores están en la memoria caché.

Un Iterator solo se puede usar una vez porque es un puntero transversal en una colección, y no una colección en sí misma. Lo que lo hace especial en Scala es el hecho de que puede aplicar transformación, como map y filter y simplemente obtener un nuevo Iterator que solo aplicará estas transformaciones cuando solicite el siguiente elemento.

Scala solía proporcionar iteradores que podían reiniciarse, pero eso es muy difícil de admitir de forma general, y no hacían la versión 2.8.0.

Las vistas deben verse 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 dijo, todas las transformaciones se vuelven a aplicar cada vez que necesita recuperar elementos de ella.

Tanto el Iterator como las vistas tienen excelentes características de memoria. Stream es agradable, pero, en Scala, su principal ventaja es escribir secuencias infinitas (particularmente secuencias definidas recursivamente). Sin embargo, uno puede evitar guardar todo el Stream en la memoria asegurándose de no mantener una referencia a su head (por ejemplo, usando def lugar de val para definir el Stream ).

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