In collezioni Scala, se si vuole iterare su una collezione (senza restituire risultati, vale a dire fare un effetto collaterale su ogni elemento della collezione), può essere fatto sia conScala: "map" vs "foreach" - c'è qualche motivo per usare "foreach" nella pratica?
final def foreach(f: (A) ⇒ Unit): Unit
o
final def map[B](f: (A) ⇒ B): SomeCollectionClass[B]
Con l'eccezione di possibile mappatura pigrizia (*), dal punto di vista dell'utente finale, vedo a zero differenze in queste invocazioni:
myCollection.foreach { element =>
doStuffWithElement(element);
}
myCollection.map { element =>
doStuffWithElement(element);
}
dato che posso semplicemente ignorare quali output della mappa. Non riesco a pensare di qualsiasi motivo specifico per cui dovrebbero esistere due metodi diversi & essere utilizzato, quando map
sembra includere tutte le funzionalità di foreach
, e, di fatto, sarei praticamente impressionato se un compilatore intelligente & VM non sarà ottimizzare la creazione dell'oggetto di raccolta dato che non è assegnato a nulla, né letto, né utilizzato ovunque.
Quindi, la domanda è - ho ragione - e non vi sono motivi per chiamare lo foreach
in un punto qualsiasi del codice?
Note:
(*) Il concetto di mappatura pigro, as throughly illustrated in this question, potrebbe cambiare le cose un po 'e giustificare l'uso di foreach
, ma per quanto posso vedere, si ha la necessità particolare di inciampare su un LazyMap
, normale
(**) Se uno non sta usando una collezione, ma scrittura uno, allora si potrebbe inciampare rapidamente sul fatto che la sintassi sintassi for
comprensione è in realtà uno zucchero sintassi che genera chiamata "foreach", vale a dire queste due righe generare il codice del tutto equivalente:
for (element <- myCollection) { doStuffWithElement(element); }
myCollection.foreach { element => doStuffWithElement(element); }
Quindi, se uno si preoccupa di altre persone che utilizzano tale classe di raccolta con for
sintassi, si potrebbe ancora voglia di implementare foreach
metodo.
È bello usare 'foreach' invece di' map' per distinguere tra le funzioni di effetto collaterale e non di effetto collaterale. Non mi interessa se il compilatore ottimizza l'uno per l'altro. La differenza rende più evidente lo scopo del codice. –
Per fare un passo avanti rispetto a LimbSoup, preferisco usare 'for ..' (sans yield) invece di' .foreach' direttamente come ulteriore (per me) mostra la divisione tra iterazione * per * effetti collaterali e una trasformazione per la sequenza. Inoltre, può essere pericoloso presumere che la sequenza che viene iterata non sia-pigra. – user2864740
Al contrario, * I * sarebbe fortemente impressionato se il corrente compilatore Scala e/o la JVM sono in grado di ottimizzare la 'mappa' con il codice' foreach' se il risultato non viene utilizzato. Mi sembra una ** estremamente ** ottimizzazione non banale. – ziggystar