Scala: странная ошибка несоответствия типов - PullRequest
1 голос
/ 25 июля 2010

Допустим, у меня есть такая функция (это только пример, поэтому не предлагайте мне лучшие способы создания массива стилей 0,1,2, ...):

def createArray(size: Int): Array[Int] = {
  for (i <- 0 until size) yield i
}

Но компилятор расстраивается из-за загадочной ошибки несоответствия типов:

(fragment of compare-images.scala):39: error: type mismatch;
 found   : RandomAccessSeq.Projection[Int]
 required: Array[Int]
      for (i <- 0 until size) yield i
            ^
one error found
!!!
discarding <script preamble>

Я уверен, причина в том, что тип возвращаемого метода until равен Range, а не Array. Но почему компилятор не может просто приводить типы? Интересно, что проблема исчезает, когда я удаляю тип возврата моей функции:

def createArray(size: Int) = {
  for (i <- 0 until size) yield i
}

Но я хочу, чтобы моя функция возвращала Array ...

У меня также есть другая функция, которая выглядит следующим образом:

def screateArray2: Array[Int] = {
  val a = Array(1,2,3,4,5)
  for (i <- a) yield i
}

Компилируется без проблем. Он выдает значения очень похоже на первый пример, но не использует пока метод ...

Я что-то упускаю из системы типов Scala?

Я довольно новичок в Scala.

РЕДАКТИРОВАТЬ: я вроде как решил мою проблему следующим образом:

def crop(data: Array[Int]): Array[Int] = (
  for (i <- 0 until data.size) yield i
).toArray

Но, на мой взгляд, это совсем не читабельно ...

Ответы [ 3 ]

5 голосов
/ 25 июля 2010

Вы не можете разыгрывать типы только потому, что Array не является Range или суперклассом этого класса. Я думаю, что их самый распространенный супертип будет IndexedSeq. Таким образом, ваш пример будет похож на метод, который вы объявляете возвращающим Int, а реализация возвращает, например, String. Однако у Range есть метод toArray, поэтому, если вы хотите использовать стиль до и вернуть массив, вы можете сделать это следующим образом:


scala> (for (i <- 0 until 5) yield i).toArray
res0: Array[Int] = Array(0, 1, 2, 3, 4)

или, если вам это не нравится, есть другой способ, но он не использует стиль до:


scala> for (i <- Array.range(0,5)) yield i          
res1: Array[Int] = Array(0, 1, 2, 3, 4)

Кроме того, отметьте этот связанный вопрос для получения пользовательских типов из для понимания

3 голосов
/ 25 июля 2010

Итак, как насчет этого:

scala> import scala.collection.breakOut
import scala.collection.breakOut

scala> def createSet(size: Int): Set[Int] = (
     |     for(i <- 0 until size) yield i
     | )(breakOut)
createSet: (size: Int)Set[Int]

scala> def createList(size: Int): List[Int] = (
     |     for(i <- 0 until size) yield i
     | )(breakOut)
createList: (size: Int)List[Int]

scala> def createArray(size: Int): Array[Int] = (
     |     for(i <- 0 until size) yield i
     | )(breakOut)
createArray: (size: Int)Array[Int]

scala> createArray(10)
res3: Array[Int] = Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

scala> createList(5)
res4: List[Int] = List(0, 1, 2, 3, 4)

scala> createSet(4)
res5: Set[Int] = Set(0, 1, 2, 3)

scala>
1 голос
/ 25 июля 2010

Решение Арджана можно сократить до:

 def createArray(size: Int) = (0 until size).toArray

[Редактировать] Конечно, вы можете удалить ненужные значения перед созданием массива

 def createArray(size: Int) = (0 until size).filter(LOTSOFINTERESTINGSTUFF).toArray
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...