Scala For-Loop / For-Yield Optimization?

836 views Asked by At

In Scala, for and for-yield loops are usually translated to a squence of map, flatMap and filter calls with Lambdas. Since the compiler converts there Lambdas into Anonymous Classes instead of Java 8's fancy invokedynamic / LambdaMetafactory / Unsafe.defineAnonymousClass system. This obviously creates a lot of overhead for the temporary classes and their instances, as well as the overhead of the map, flatMap and filter operations, which usually copy their underlying collections. Is there any particular reason to use the functional approach to a problem when the generally faster iterative approach is available, at least on the bytecode level?

For example, why does

for {
  sl <- l
  el <- sl
  if el > 0
} println el.toString.length

translate to

l.flatMap(sl => sl.filter(el => el > 0).foreach(el => println el.toString.length))

Instead of

for (sl <- l) // Iterable for loop
{
    for (el <- sl) // Iterable for loop
    {
        println el.toString.length
    }
}
1

There are 1 answers

4
Daenyth On BEST ANSWER

It's implemented that way because that's how the SLS defines it. The rules are rather large to paste here, but they're fully included in the spec.

For Comprehensions and For Loops

Example The following code produces all pairs of numbers between 1 and n−1 whose sums are prime.

for  { i <- 1 until n
       j <- 1 until i
       if isPrime(i+j)
} yield (i, j)

The for comprehension is translated to:

(1 until n)
  .flatMap {
     case i => (1 until i)
       .withFilter { j => isPrime(i+j) }
       .map { case j => (i, j) } }