Scala: strange type mismatch error
Let's say I have a function like this (it's only an example, so do not offer me better ways to create 0,1,2,... style array):
def createArray(size: Int): Array[Int] = {
for (i <- 0 until size) yield i
}
But the compiler get upset with some mysterious type mismatch error:
(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>
I'm sure, the reason has something to do with the fact that until
method's return type is Range
, not Array
. Yet, why the compiler can't just cast the types?
Interestingly the problem goes away when I remove the return type of my function:
def createArray(size: Int) = {
for (i <- 0 until size) yield i
}
But I want my function to return Array
...
I also have开发者_Python百科 another function, which goes like this:
def screateArray2: Array[Int] = {
val a = Array(1,2,3,4,5)
for (i <- a) yield i
}
It compiles without any problems. It yields values very similarly to the first example, but doesn't use until method...
Am I missing something about Scala's type system?
I'm quite new to Scala.
EDIT: I sort of solved my problem like this:
def crop(data: Array[Int]): Array[Int] = (
for (i <- 0 until data.size) yield i
).toArray
But in my view it's anything but readable...
You can't cast the types just because an Array is not a Range, nor a superclass of it. I think their most common supertype would be IndexedSeq
. So your example would be similar to a method which you declare to return an Int, while the implementation would return a String, for instance. Range does have a toArray
method, however, so if you want to use the until style and return an Array, you can do it like this:
scala> (for (i <- 0 until 5) yield i).toArray
res0: Array[Int] = Array(0, 1, 2, 3, 4)
or, if do don't like this, there's another way, but that doesn't use the until style:
scala> for (i <- Array.range(0,5)) yield i
res1: Array[Int] = Array(0, 1, 2, 3, 4)
Also, check this related question for returning custom types from a for comprehension
So, How about this one:
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>
Arjan's solution can be shortened to:
def createArray(size: Int) = (0 until size).toArray
[Edit] Of course you can remove values you don't need before you create the array
def createArray(size: Int) = (0 until size).filter(LOTSOFINTERESTINGSTUFF).toArray
精彩评论