Goal: Efficiently do something for each element in a list, and then return the original list, so that I can do something else with original list. For example, let lst
be a very large list, and suppose we do many operations to it before applying our foreach. What I want to do is something like this:
lst.many_operations().foreach(x => f(x)).something_else()
However, foreach
returns a unit. I seek a way to iterate through the list and return the original list supplied, so that I can do something_else()
to it. To reduce the memory impact, I need to avoid saving the result of lst.many_operations()
to a variable.
An obvious, but imperfect, solution is to replace foreach
with map
. Then the code looks like:
lst
.many_operations()
.map(x => {
f(x)
x
}).something_else()
However, this is not good because map
constructs a new list, effectively duplicating the very large list that it iterated through.
What is the right way to do this in Scala?
CodePudding user response:
The simplest way seems to be:
lst.foreach(many_operations)
lst.foreach(something_else)
However: using side effects is really not a good idea. I would urge you to revisit your design to use explicit pure transformations rather than side effects and mutations.
To address your concern about having multiple lists in memory at the same time, you can use view
or iterator
to emulate streaming processing, and discard intermediate results you do not need to use again:
val newList = lst.iterator
.map(foo)
.map(bar)
.map(baz)
.toList
(lst
will get garbage collected if you do not reference it again).