开发者

Why does map/filter ... not work with an Array of Nothing?

Isn't Nothing a subtype of all types?

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

It's weird that this doesn't work.

开发者_Python百科Is this specified, a feature or a bug?


When you see weird behavior involving Nothing, it's because the type inference algorithm thinks that it inserted Nothing itself, since it is introduced during type inference: if nothing is known about a type variable then it is bounded by Any and Nothing. It has long been on my list of things to do to see if I can introduce a new internal-only bottom type for that purpose so user-level Nothing and inference-level Nothing are not intermingled, but it's a pretty ambitious task. Still, I might now be hardcore enough to try it.


I suspect Scala shouldn't let you do that kind of Array[Nothing] instantiation. There are by definition no instances of nothing around, yet your array looks like it's filled with Nothings that are null, but null is not a valid value for Nothing. This for instance fails with the error type mismatch; found : Null(null) required: Nothing

val n: Nothing = null

So I'd expect to run into trouble each time you can actually fool the system to believe you are finally getting hold of a much sought for instance of Nothing

Here's another weird case. Run this:

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

}


Note that the Scala Array type is invariant. So Nothing being a subtype of everything may not be relevant.

Also map and filter are not defined on Array. Implicit conversions in Predef are used to provide such methods for arrays.

So the compiler is unable to find an implicit conversion from Array[Nothing] to something that has the map or filter defined. Using the REPL, I can actually see that such an implicit conversion should be available:

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)

So the question becomes why the compiler does not consider the genericArrayOps conversion.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜