I'm trying to understand the behavior of Scala for-loop implicit box/unboxing of "numerical" types. Why does the two first fail but not the rest?
1) Fails:
scala> for (i:Long <- 0 to 10000000L) {}
<console>:19: error: type mismatch;<br>
found : Long(10000000L)
required: Int
for (i:Long <- 0 to 10000000L) {}
^
2> Fails:
scala> for (i <- 0 to 10000000L) {}
<console>:19: error: type mismatch;
found : Long(10000000L)
required: Int
for (i <- 0 to 10000000L) {}
^
3) Works:
scala> for (i:Long <- 0L to 10000000L) {}
4) Works:
scala> for (i <- 0L to 10000000L) {}
It has nothing to do with the for-loop:
0 to 1L //error
0 to 1 //fine
0L to 1L //fine
0L to 1 //fine
It's just because the to
method available to Int
expects an Int
as its argument. So when you give it a Long
it doesn't like it, and you get an error.
Here's the definition of the to
method, found on RichInt
:
def to(end: Int): Range.Inclusive = Range.inclusive(self, end)
The desugaring and implicit transformation of numerical types is inconsistent i.e differ between the "for/comprehension" expressions compared to assignment operations. Please feel free to prove otherwise or at least point where the argument below is flawed:
In fact, during numeric assignment the Destination type is dominant.
var l:Long = 0
becomes:
val l: Long = 0L
var l:Long = 0.toInt
becomes:
var l: Long = 0.toInt.toLong
During "for/comprehension" expressions the Source type is dominant:
for (i:Long <- 0 to 1000000000L) { }
becomes:
0.to(1000000000L).foreach(((i: Long) => ()))
for (i <- 0L to 1000000000L) { }
becomes:
scala.this.Predef.longWrapper(0L).to(1000000000L).foreach[Unit](((i: Long) => ()))
(ps: output generated with the "-Xprint:typer -e" compiler flag. ds)