2012-03-27 5 views
10

Что стоит за ограничением размера NumericRange Int в понимании Scala for-loop? Возможно ли (без большой головной боли) расширить «для/Seqs» NumericRange, чтобы использовать Long (или что-то большее, чем Int.MaxValue)?Почему Scala for-loop (и внутренние) NumericRange ограничивается размером Int и как разрабатывать функциональность?

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) 

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

ответ

7

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

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

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

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

+0

Это не только Range, это то, что вы создаете. Вы можете передать любую монаду для понимания. – drexin

+0

@Ed Staub - это точно моя точка, то есть почему диапазон count() ограничен Int! ИМХО, это довольно странно, но остается большой вопрос: это ошибка или функция ;-) – IODEV

+0

@drexin: любая идея, почему диапазон значений по умолчанию равен Int? – IODEV

8

В Scala нет для цикла, но для понимания. Он работает иначе, чем цикл. На самом деле ваш для постижение переводится на:

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

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

var i = 0L 
while(i < 10000000000) { 
    // do stuff 
    i+=1 
} 
+0

Спасибо за повторную игру. Я прекрасно понимаю синтаксис сакса понимания. Но точка была «почему» Seq ограничена (как уже говорилось в вопросе), и если Seq легко расширяется? – IODEV

+0

, так что вы в основном имеете в виду, что для/понимания недостаточно зрело, чтобы использоваться в производстве? Является ли это недостатком дизайна библиотеки или языковой проблемой? – IODEV

+0

Нет, это означает, что для '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'требуется последовательность элементов, – Nicolas

2

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

+0

Итак, чтобы справиться с коллекциями Seq, большими, чем Int.MaxSize, нам нужен BigSeq ? ;-) – IODEV

+2

@IODEV Существует практический вопрос полезности коллекций, которые являются большими. Я думаю, что реальная проблема заключается в том, что, пожалуй, диапазоны не должны быть коллекциями, просто имеют конверсии _into_ коллекций. –

1

Вы не можете рассчитывать элементы, пока их количества не вписываются в 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 
+0

Хорошо работает на Scala 2.9, Scala 2.10 кричит следующее: scala> def longRange (from: Long, to: Long) = new Iterator [Long] { | частный var i: Long = от | def hasNext = i : 10: ошибка: перегруженный метод значение <альтернативами: ... (х: Long) Логическое (х: Int) Boolean (х: Char) Boolean (х: Short) Логическое (х: Byte) Boolean не может быть применен к (scala.collection.immutable.IndexedSeq [Long]) четкости hasNext = я <к ^ – Ochoto

+0

Похоже Scala компилятором смущает 'в' слово, потому что есть метод с таким именем. Возможно, что-то пошло не так в их определении синтаксиса. BTW, я начал думать, что эта часть синтаксиса scala (позволяющая вместо метода «стиль пространства» вместо «dot style» для всех имен использовать не только «специальные символы», такие как '+', '++', '::' и т. д.) является злом. Вот рабочий пример: http://ideone.com/Z5989Q, и если мы переименуем 'end' в' to', он не компилируется: http://ideone.com/6FADFE. Возможно, это законно, чтобы сообщить об ошибке. –

 Смежные вопросы

  • Нет связанных вопросов^_^