2010-07-25 127 views
1

比方说,我有这样的功能(这只是一个例子,所以不要给我更好的方法来创建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 

但在我看来,这是什么,但可读......

回答

5

你不能投的类型,只是因为数组不范围,也不是它的超类。我认为他们最常见的超类型是IndexedSeq。因此,您的示例将类似于您声明返回Int的方法,而实现将返回String,例如。范围内确实有一个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) 

此外,检查this related question用于从返回自定义类型的理解

+0

我应该说之前你不需要值“推断“(或者Scala编译器用来匹配类型)而不是”cast“。 – 2010-07-25 09:08:10

+0

但是类型不匹配,因为Range不是Array的子​​类型,所以在这里没有推断正确结果类型的问题。你必须做一个转换来获得。 – 2010-07-25 09:40:59

+0

是的,但你真的不必是一个天才编译器来自动将Range转换为Array,而不是打扰类型不匹配错误:) – 2010-07-25 18:32:27

3

所以,这个怎么样:

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> 
+0

'(breakOut)'部件究竟做了什么? 我在抱怨我的'.toArray'解决方案是不可读的:) – 2010-07-25 18:43:52

+0

@Vilius是的,这不是特别可读,我甚至不认为这是可能的。查看关于Scala的理解和关于'breakOut'的问题,正如其他地方所解释的那样。 – 2010-08-09 19:39:04

1

阿尔扬的解决方案可以简化为:

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

[编辑]当然,你可以删除您创建数组

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

我的实际方法更像'for(i < - 0直到size; if(LOFT OF STUFF HERE))yield i''。为了举例,我只是简化了它。 – 2010-07-25 18:29:29

+0

看我的[编辑] ... – Landei 2010-07-25 18:53:18

+0

其实,'withFilter'会比'filter'更好。 – 2010-08-09 19:36:06