2011-04-30 76 views
3

是不是所有類型的子類型?爲什麼地圖/過濾器...不適用於無數數組?

scala> val array = new Array(5) 
array: Array[Nothing] = Array(null, null, null, null, null) 

scala> array.map(_ => 42) 
<console>:9: error: value map is not a member of Array[Nothing] 
     array.map(_ => 42) 
      ^

scala> array.filter(_ != 42) 
<console>:9: error: value filter is not a member of Array[Nothing] 
     array.filter(_ != 42) 
      ^

這很奇怪,這是行不通的。

這是指定的功能還是錯誤?

回答

7

當你看到涉及Nothing的奇怪行爲時,這是因爲類型推斷算法認爲它自己插入了Nothing,因爲它是在類型推斷期間引入的:如果對類型變量沒有任何瞭解,則它由Any和Nothing限定。長久以來,我一直在列舉一些事情來確定是否可以爲此目的引入新的內部唯一底層類型,以便用戶級別無與推理級別混合,但這是一項非常雄心勃勃的任務。儘管如此,我現在可能已經足夠堅強來嘗試它了。

4

我懷疑Scala不應該讓你做那種Array[Nothing]實例化。根據定義,沒有任何附近有任何實例,但是您的數組看起來像是用Nothing s填充,但是null不是Nothing的有效值。例如,這將失敗,錯誤type mismatch; found : Null(null) required: Nothing

val n: Nothing = null 

所以我希望給每個你其實可以騙過系統,相信你終於得到的多尋求的Nothing例如保持時間遇到了麻煩......

這是另一個奇怪的情況。執行此操作:

object Main { 

    class Parametrized[T] { var value: T = _ } 

    def main(args: Array[String]) { 
    val p = new Parametrized // typed as Parametrized[Nothing] 
    val n = p.value // n is now actually an instance of Nothing... isn't it? 
    println(p.value) // prints null, but null is not an instance of Nothing 
    println(n)  // throws NullPointerException... 
    } 

} 
+0

'null'並不是真的'null',它更像是一個'throw new NullPointerException'。 'toString'有點誤導。 – soc 2011-04-30 18:23:28

+0

@soc我意識到現在:編譯器實際上通過拋出「unboxes」null作爲Nothing。有趣的是,它並沒有在上面的'println(p.value)'上做。 – 2011-05-02 07:47:46

4

請注意,Scala數組類型是不變的。因此Nothing是一切的一個子類型可能不相關。

另外mapfilter沒有在Array上定義。 Predef中的隱式轉換用於爲數組提供此類方法。

因此,編譯器無法找到從Array[Nothing]mapfilter定義的內容的隱式轉換。使用REPL,我可以清楚地看到,這樣的隱式轉換應提供:

scala> val conv = implicitly[Array[Nothing] <%< collection.mutable.ArrayOps[Nothing]] 

conv: <%<[Array[Nothing],scala.collection.mutable.ArrayOps[Nothing]] = <function1> 

scala> conv(new Array[Nothing](5)).filter(_ => true) 
res8: Array[Nothing] = Array(null, null, null, null, null) 

於是問題就來了,爲什麼編譯器不考慮genericArrayOps轉換。

+0

在REPL中測試隱式轉換是否可用的好方法! – 2011-04-30 18:30:55

相關問題