2010-07-25 140 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