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?
-
the for loop allocates 10^9 intspathikrit– pathikrit2013-04-27 10:40:03 +00:00Commented Apr 27, 2013 at 10:40
-
What version of scala is this related to?Richard Sitze– Richard Sitze2013-04-27 20:23:04 +00:00Commented Apr 27, 2013 at 20:23
1 Answer
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