Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the Scala for-loop (and internals) NumericRange restricted to Int size and how to elaborate the functionality?

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!

like image 200
IODEV Avatar asked Mar 27 '12 11:03

IODEV


People also ask

Does Scala have for loops?

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.

How do you make a nested for loop in Scala?

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… } }


2 Answers

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.

like image 66
Ed Staub Avatar answered Sep 23 '22 00:09

Ed Staub


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
like image 20
Display Name Avatar answered Sep 21 '22 00:09

Display Name