Почему цикл Scala for (и внутренние компоненты) NumericRange ограничен размером Int и как разработать функциональность? - PullRequest
10 голосов
/ 27 марта 2012

Что стоит за ограничением размера NumericRange Int для понимания цикла for Scala? Можно ли (без особой головной боли) расширить «for / Seqs» NumericRange для использования Long (или чего-то большего, чем 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)

-
Заранее спасибо!

Ответы [ 4 ]

9 голосов
/ 27 марта 2012

В Scala нет цикла «for», но есть «for-понимания». Это работает не так, как цикл. На самом деле ваше понимание понимается как:

(0L to 10000000000).map { i => // (0L to 10000000000) == collection.immutable.NumericRange.inclusive(0L, 10000000000,1)
  // block
}

Ограничение не в фор-понимании, а в типе Seq, который не может содержать больше, чем элементы Int.MaxValue. Если вам действительно нужен цикл 10000000000x, вы все равно можете использовать

var i = 0L
while(i < 10000000000) {
  // do stuff
  i+=1
}
7 голосов
/ 27 марта 2012

Краткий ответ - кажется, что это «особенность» - по крайней мере, она работает так, как задумано.

Как указывал @drexin, реализация «to» ограничена наличием диапазона Int.Однако ...

Проблема в том, что NumericRange [T] .count (), .numRangeElements и .length () возвращает Int - независимо от того, что такое T.В данном случае это NumericRange [Long], где кажется немного неправильным ограничивать count () 31 битом, ИМХО.
Однако ...

При просмотре вопросов Jira это выглядит так:работать как задумано.См., Например, SI-4370 .Но просто чтобы убедиться, что это было продумано с этой точки зрения, я ввел SI-5619 .

2 голосов
/ 25 августа 2012

Вы не можете считать элементы, если их количество не вписывается в Int, потому что объявлено, что length возвращает Int, но вот ярлык: вы можете создать итераторов с любой фактический размер, если вы не пытаетесь их посчитать.

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
2 голосов
/ 27 марта 2012

Методы size и length возвращают Int, поэтому они не смогут вернуть значение, большее Int.MaxValue.На Seq также метод apply принимает Int, страдающий той же проблемой.Поэтому коллекции Scala , как и коллекции Java , ограничены Int.MaxValue элементами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...