Innanzitutto, sono tutti non severi . Questo ha un significato matematico particolare legato alle funzioni, ma, fondamentalmente, significa che sono calcolate su richiesta anziché in anticipo.
Stream
è davvero una lista pigra. In effetti, a Scala, a Stream
è a di List
cui tail
è a lazy val
. Una volta calcolato, un valore rimane calcolato e viene riutilizzato. Oppure, come dici tu, i valori vengono memorizzati nella cache.
An Iterator
può essere usato una sola volta perché è un puntatore a croce in una raccolta e non una raccolta in sé. Ciò che lo rende speciale a Scala è il fatto che è possibile applicare la trasformazione, come map
e filter
e semplicemente ottenere un nuovo Iterator
che si applicano soltanto queste trasformazioni quando si chiede l'elemento successivo.
Scala forniva iteratori che potevano essere ripristinati, ma che è molto difficile da supportare in modo generale, e non hanno realizzato la versione 2.8.0.
Le viste devono essere visualizzate in modo molto simile a una vista del database. È una serie di trasformazione che si applica a una raccolta per produrre una raccolta "virtuale". Come hai detto, tutte le trasformazioni vengono riapplicate ogni volta che è necessario recuperarne gli elementi.
Entrambe Iterator
e le viste hanno eccellenti caratteristiche di memoria. Stream
è bello, ma, alla Scala, il suo principale vantaggio è scrivere infinite sequenze (in particolare sequenze definite in modo ricorsivo). Si può evitare di mantenere tutto Stream
in memoria, tuttavia, assicurandosi di non mantenere un riferimento al suo head
(ad esempio, usando def
invece di val
definire il Stream
).
A causa delle penalità subite dalle viste, di solito force
si dovrebbe farlo dopo aver applicato le trasformazioni o tenerlo come una vista se si prevede che solo pochi elementi verranno recuperati, rispetto alla dimensione totale della vista.