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 Nothing
s 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.
精彩评论