Range with more than Int.MAX_VALUE elements

While I was going through scaladoc of Range, I read that it is possible to create Range with more than MAX_VALUE elements. And it is safe to call some operations like head, drop, take.
However, when I tried it, ai was getting exception.

For e.g:
1 to 3456789128 take 2

I thought it will successfully create Range(1,2), but it threw exception on running it.

What is wrong in the way I did? Or did I understand the doc wrongly?

I would like to help, but it’s unnecessarily difficult to help when I can’t copy and paste the sample code you provided, since you provided it in the form of a screenshot. Can you provide the code as text?

This forum allows Markdown, so you can use Markdown syntax to post properly indented code.

Also, what version of Scala are you using?

I am sorry, I posted it from my mobile. Here is the sample code.

object RangeSamples extends App {
  val range = 1L to 3147483649L //More than Integer.MAX_VALUE
  println("First 5 Value = "+range.take(5)) //throws IllegalArgumentException: More than Int.MaxValue elements
  println("First Value = "+range.head) //throws IllegalArgumentException: More than Int.MaxValue elements
}

on range.take(5), I got the exception as

java.lang.IllegalArgumentException: More than Int.MaxValue elements.

Scala Version : 2.12.11

1 Like

1L to 3147483649L is a NumericRange, not a Range. Range is specific to Int. NumericRange handles the other numeric types.

https://www.scala-lang.org/api/2.12.11/scala/collection/immutable/NumericRange.html doesn’t have the wording about “overfull” ranges that you saw on https://www.scala-lang.org/api/2.12.11/scala/collection/immutable/Range.html.

historical reference: https://github.com/scala/scala/pull/3437

Thank you for the quick clarification.
However, I have a doubt. Is it possible to create a range(not of type NumericRange) of numbers more that Integer.MAX_VALUE?

While trying out some sample program, where the user inputs a large number, and I need to to get the numbers between 1 and USER_INPUT_END based on a certain condition. I tried using Range and got this exception for very large input.
I did it with a simple recursion logic, however, I was wondering if it can be done using Range instead of NumericRange ?

The below example is from Range scaladoc. Is this creating a NumericRange right ?
{{{
val r1 = 0 until 10
val r2 = r1.start until r1.end by r1.step + 1
println(r2.length) // = 5
}}}

I am a bit confused. Also, I though NumericRange is a sub class of Range, but found it otherwise.
Sorry if it is a stupid question.

Is it possible to create a range(not of type NumericRange) of numbers more that Integer.MAX_VALUE?

Did you try it yourself? What did you try and what happened?

I was wondering if it can be done using Range instead of NumericRange

Range only supports Ints.

The below example is from Range scaladoc. Is this creating a NumericRange right ?

Nope, it’s a Range. You can see it in the REPL:

scala 2.13.3> val r1 = 0 until 10
            | val r2 = r1.start until r1.end by r1.step + 1
            | println(r2.length) // = 5
            | 
5
val r1: scala.collection.immutable.Range = Range 0 until 10
val r2: scala.collection.immutable.Range = Range 0 until 10 by 2

I don’t get it. I’m using NumericRange.Exclusive[Long]

object Main {

  def main(args: Array[String]): Unit = {
    import scala.collection.immutable.NumericRange
    var result = 0L
    val range: NumericRange.Exclusive[Long] = 0L until Int.MaxValue * 10L
    for (j <- range) {
      result += j
    }
  }

}

scala still tell me

Exception in thread "main" java.lang.IllegalArgumentException: More than Int.MaxValue elements.
	at scala.collection.immutable.NumericRange$.check$1(NumericRange.scala:319)
	at scala.collection.immutable.NumericRange$.count(NumericRange.scala:329)
	at scala.collection.immutable.NumericRange.numRangeElements$lzycompute(NumericRange.scala:54)
	at scala.collection.immutable.NumericRange.numRangeElements(NumericRange.scala:53)
	at scala.collection.immutable.NumericRange.length(NumericRange.scala:56)
	at scala.collection.immutable.NumericRange.foreach(NumericRange.scala:74)
	at tech.yusur.Main$.main(Main.scala:20)
	at tech.yusur.Main.main(Main.scala)

Then I found limit is still Int.MaxValue

      val limit = num.fromInt(Int.MaxValue)
      def check(t: T): T =
        if (num.gt(t, limit)) throw new IllegalArgumentException("More than Int.MaxValue elements.")
        else t

My scala version is 2.12.16

It seems scala unsupport “Range(or NumericRange) with more than Int.MAX_VALUE elements”, using while instead

Consult the doc for Range, which explains you can’t do much with an “overfull” range. (I would prefer the term “supersaturated”.)

scala> val ns = Range.Long(0, Int.MaxValue * 10L, 1)
val ns: scala.collection.immutable.NumericRange.Exclusive[Long] = NumericRange 0 until 21474836470

scala> val xs = ns by 1000
val xs: scala.collection.immutable.NumericRange[Long] = NumericRange 0 until 21474836470 by 1000

scala> .size
val res2: Int = 21474837

scala> ns.size
java.lang.IllegalArgumentException: More than Int.MaxValue elements.
  at scala.collection.immutable.NumericRange$.check$1(NumericRange.scala:330)
  at scala.collection.immutable.NumericRange$.count(NumericRange.scala:340)
  at scala.collection.immutable.NumericRange.length$lzycompute(NumericRange.scala:75)
  at scala.collection.immutable.NumericRange.length(NumericRange.scala:75)
  at scala.collection.SeqOps.size(Seq.scala:200)
  at scala.collection.SeqOps.size$(Seq.scala:200)
  at scala.collection.AbstractSeq.size(Seq.scala:1188)
  ... 30 elided

I thought the linked PR said it also fixes last, but

scala> xs.last
val res4: Long = 21474836000

scala> ns.last
java.lang.IllegalArgumentException: More than Int.MaxValue elements.
  at scala.collection.immutable.NumericRange$.check$1(NumericRange.scala:330)
  at scala.collection.immutable.NumericRange$.count(NumericRange.scala:340)
  at scala.collection.immutable.NumericRange.length$lzycompute(NumericRange.scala:75)
  at scala.collection.immutable.NumericRange.length(NumericRange.scala:75)
  at scala.collection.immutable.NumericRange.last(NumericRange.scala:83)
  ... 30 elided

and frankly the discussion on the PR about reducing “wtf/method” itself has a high “wtf/comment”.