3

Nothing 不是所有类型的子类型吗?

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)
             ^

奇怪的是,这不起作用。

这是指定的,功能还是错误?

4

3 回答 3

7

当您看到涉及 Nothing 的奇怪行为时,这是因为类型推断算法认为它自己插入了 Nothing,因为它是在类型推断期间引入的:如果对类型变量一无所知,则它受 Any 和 Nothing 的限制。长期以来,我一直在做的事情清单上,看看我是否可以为此目的引入一个新的仅限内部的底部类型,这样用户级的 Nothing 和推理级的 Nothing 就不会混合在一起,但这是一项非常雄心勃勃的任务。不过,我现在可能已经够硬核了,可以尝试一下。

于 2011-05-01T18:28:00.693 回答
4

请注意,Scala Array 类型是不变的。因此Nothing,作为所有事物的子类型可能无关紧要。

mapfilter没有定义在Array. 隐式转换Predef用于为数组提供此类方法。

因此编译器无法找到从Array[Nothing]具有maporfilter定义的内容的隐式转换。使用 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转换。

于 2011-04-30T17:27:40.107 回答
4

我怀疑 Scala 不应该让你做那种Array[Nothing]实例化。根据定义,周围没有任何实例,但您的数组看起来像是填充了Nothingnull 的 s,但 null 不是Nothing. 例如,这会因错误而失败type mismatch; found : Null(null) required: Nothing

val n: Nothing = null

所以我预计每次你实际上可以欺骗系统相信你终于掌握了一个非常受欢迎的例子时会遇到麻烦Nothing......</p>

这是另一个奇怪的案例。运行这个:

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...
  }

}
于 2011-04-30T16:39:05.567 回答