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 Int
s.
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”.