What's behind the NumericRange Int size restriction on the Scala for-loop comprehension? Is it possible (without to much headache) to extend "for/Seqs" NumericRange to make use of Long (or anything bigger than Int.MaxValue)?
scala>
for (i: Long <- 0L to 10000000000) {}
java.lang.IllegalArgumentException: 0 to 10000000000L by 1: "seqs cannot contain more than Int.MaxValue elements." at scala.collection.immutable.NumericRange$.count(NumericRange.scala:227) at scala.collection.immutable.NumericRange.numRangeElements(NumericRange.scala:53) at scala.collection.immutable.NumericRange.length(NumericRange.scala:55) at scala.collection.immutable.NumericRange.foreach(NumericRange.scala:73) at .<init>(<console>:19) at .<clinit>(<console>) at .<init>(<console>:11) at .<clinit>(<console>) at $print(<console>) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704) at scala.tools.nsc.interpreter.IMain$Request$$anonfun$14.apply(IMain.scala:920) at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:43) at scala.tools.nsc.io.package$$anon$2.run(package.scala:25) at java.lang.Thread.run(Thread.java:680)
--
Thanks in advance!
In Scala, for loop is also known as for-comprehensions. A for loop is a repetition control structure which allows us to write a loop that is executed a specific number of times. The loop enables us to perform n number of steps together in one line.
For nesting loops, we can place the second loop inside the body of the first loop. This is the traditional way and most used one too. And is done like this, loop1{ loop2{ //code to be executed… } }
Short answer- it appears to be a "feature" - at least, it's working as designed.
As @drexin pointed out, the implementation of "to" is limited to having an Int range. However...
The problem is that NumericRange[T].count(), .numRangeElements, and .length() returns an Int - regardless of what T is. In this case, it's a NumericRange[Long], where it seems a bit wrong to have count() limited to 31 bits, IMHO.
However...
From browsing Jira issues, this appears to be working as designed. See, e.g., SI-4370. But just to be sure it's been thought out from this perspective, I entered SI-5619.
You cannot count elements as long as their count doesn't fit in Int
, because length
is declared to return Int
, but here is the shortcut: you can create iterators with any actual size, as long as you don't try to count them.
scala> def longRange(first: Long, last: Long) = new Iterator[Long] {
private var i = first
def hasNext = i < last
def next = {val r = i; i += 1; r}
}
longRange: (from: Long, to: Long)java.lang.Object with Iterator[Long]
scala> val lol = longRange(0, Long.MaxValue) map (x => x * x)
lol: Iterator[Long] = non-empty iterator
scala> lol drop 5 take 5 foreach println
25
36
49
64
81
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With