In Scala collections, if one wants to iterate over a collection (without returning results, i.e. doing a side effect on every element of collection), it can be done either with
final def foreach(f: (A) ⇒ Unit): Unit
or
final def map[B](f: (A) ⇒ B): SomeCollectionClass[B]
With the exception of possible lazy mapping(*), from an end-user perspective, I see zero differences in these invocations:
myCollection.foreach { element =>
doStuffWithElement(element);
}
myCollection.map { element =>
doStuffWithElement(element);
}
given that I can just ignore what map outputs. I can't think of any specific reason why two different methods should exist & be used, when map
seems to include all the functionality of foreach
, and, in fact, I would be pretty much impressed if an intelligent compiler & VM won't optimize out that collection object creation given that it's not assigned to anything, or read, or used anywhere.
So, the question is - am I right - and there are no reasons to call foreach
anywhere in one's code?
Notes:
(*) The lazy mapping concept, as throughly illustrated in this question, might change things a bit and justify usage of foreach
, but as far as I can see, one specifically needs to stumble upon a LazyMap
, normal
(**) If one's not using a collection, but writing one, then one would quickly stumble upon the fact that for
comprehension syntax syntax is in fact a syntax sugar that generates "foreach" call, i.e. these two lines generate fully equivalent code:
for (element <- myCollection) { doStuffWithElement(element); }
myCollection.foreach { element => doStuffWithElement(element); }
So if one cares about other people using that collection class with for
syntax, one might still want to implement foreach
method.
I can think of a couple motivations:
foreach
is the last line of a method that is of type Unit
your compiler will not give an warning but will with map
(and you need -Ywarn-value-discard
on). Sometimes you get warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
using map
but wouldn't with foreach
.map
was usedmap
and foreach
foreach
won't build a new list, so will be more efficient (thanks @Vishnu)