Reputation: 33439
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
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 Range
s 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