pathikrit
pathikrit

Reputation: 33439

Scala for-loop ranges OutOfMemoryError

Why does for {i <- (1 to 1000000000)} println(i) gives me OutOfMemoryError but (1 to 1000000000) foreach println does not? What if I have to use the for-loop syntax, what should I do?

Upvotes: 1

Views: 235

Answers (1)

Martin Ring
Martin Ring

Reputation: 5426

The two fragments are nearly equivalent. for syntax in scala is desugared by the compiler into applications of foreach, flatmap, withFilter as well as map (if you use yield). This information can be found in section 6.19 of the scala language specification.

That means the for loop

for (i <- 1 to 1000000000) println(i)

becomes desugared into

(1 to 1000000000).foreach { case i => println(i) }

which is nearly equivalent to

(1 to 1000000000) foreach println

Neither of the fragments should cause an OutOfMemoryError. You can have a look at the overridden definition of foreach for Ranges in the sources:

https://github.com/scala/scala/blob/v2.10.1/src/library/scala/collection/immutable/Range.scala#L135

There is only 1 index variable which is mutated while the loop is processed.

But it's useful to confirm that there is no extra boxing/unboxing of the index int. As it turns out, there isn't, although the stack trace to get there is slightly different for the two forms:

Predef$.println(Object) line: 287
ForTest$$anonfun$f$1.apply$mcVI$sp(Int) line: 5
Range.foreach$mVc$sp(Function1) line: 141
ForTest$.f() line: 5

Predef$.println(Object) line: 287
ForTest$$anonfun$g$1.apply(Object) line: 6
ForTest$$anonfun$g$1.apply(Object) line: 6  // boxing here
Function1$class.apply$mcVI$sp(Function1, Int) line: 39
AbstractFunction1.apply$mcVI$sp(Int) line: 12
Range.foreach$mVc$sp(Function1) line: 141
ForTest$.g() line: 6

Upvotes: 2

Related Questions