Sharvanath
Sharvanath

Reputation: 477

When should we not use "for loops" in scala?

Twitter's Effective Scala says:

"for provides both succinct and natural expression for looping and aggregation. It is especially useful when flattening many sequences. The syntax of for belies the underlying mechanism as it allocates and dispatches closures. This can lead to both unexpected costs and semantics; for example

for (item <- container) {
  if (item != 2) 
    return
}

may cause a runtime error if the container delays computation, making the return nonlocal!

For these reasons, it is often preferrable to call foreach, flatMap, map, and filter directly — but do use fors when they clarify."

I don't understand why there can be runtime errors here.

Upvotes: 2

Views: 1632

Answers (2)

samthebest
samthebest

Reputation: 31513

Simon has a very nice answer regarding the return problem. I would like to add that in general using for loops is simply bad Scala style when foreach, map, etc would do. The exception is when you want nested foreach, map, etc like behaviour and in this case a for loop, rather, to be specific, a "for comprehension" would be appropriate.

E.g.

// Good, better than for loop
myList.foreach(println)

// Ok but might be easier to understsnd the for comprehension
(1 to N).map(i => (1 to M).map((i, _)))

// Equivilent to above and some say easier to read
for {
  i <- (1 to N)
  j <- (1 to M)
} yield (i, j)

Upvotes: 1

Simon
Simon

Reputation: 113

The Twitter manual is warning that the code inside of the for may be bound inside a closure, which is (in this case) a function running inside of an execution environment that is built to capture the local environment present at the call site. You can read more about closures here - http://en.wikipedia.org/wiki/Closure_%28computer_programming%29.

So the for construct may package all of the code inside the loop into a separate function, bind the particular item and the the local environment to the closure (so that all references to variables outside of the loop are still valid inside the function), and then execute that function somewhere else, ie in another, hidden call frame.

This becomes a problem for your return, which is supposed to immediately exit the current call frame. But if your closure is executing elsewhere, then the closure function becomes the target for the return, rather than the actual surrounding method, which is what you probably meant.

Upvotes: 1

Related Questions