Home > Blockchain >  An efficient and composable foreach in Scala
An efficient and composable foreach in Scala

Time:09-27

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).

  • Related