为什么map / filter ...不适用于Nothing?

时间:2011-04-30 16:06:17

标签: arrays scala map higher-order-functions 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)
             ^

奇怪的是,这不起作用。

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

3 个答案:

答案 0 :(得分:7)

当你看到涉及Nothing的奇怪行为时,这是因为类型推断算法认为它本身插入了Nothing,因为它是在类型推断期间引入的:如果对类型变量一无所知,则它由Any和Nothing限定。长期以来一直在我要做的事情列表中,看看我是否可以为此目的引入一个新的仅内部底部类型,因此用户级别Nothing和推理级别没有任何内容没有混合,但这是一项非常雄心勃勃的任务。不过,我现在可能已经足够努力了。

答案 1 :(得分:4)

我怀疑Scala不应该让你做那种Array[Nothing]实例化。根据定义,没有任何实例,但是你的数组看起来像是Nothing,它们是空的,但是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...
  }

}

答案 2 :(得分:4)

请注意,Scala数组类型是不变的。因此Nothing是所有事物的子类型可能不相关。

map上未定义filterArrayPredef中的隐式转换用于为数组提供此类方法。

因此,编译器无法找到从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转换的原因。