[英]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): 假设我有一个像这样的函数(这只是一个例子,所以不要为我提供创建0,1,2,...样式数组的更好方法):
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
. 我敢肯定,原因与以下事实有关: until
方法的返回类型为Range
,不是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
... 但是我希望我的函数返回Array
...
I also have 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? 我是否缺少有关Scala的类型系统的信息?
I'm quite new to Scala. 我是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
. 我认为它们最常见的超类型将是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. 因此,您的示例将类似于您声明返回Int的方法,而实现将返回例如String。 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: Range确实具有toArray
方法,因此,如果要使用直到风格并返回Array,可以这样进行:
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: Arjan的解决方案可以简化为:
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.