开发者

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜