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

后端 未结 3 596
忘掉有多难
忘掉有多难 2021-01-14 06:39

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(_          


        
相关标签:
3条回答
  • 2021-01-14 06:56

    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 讨论(0)
  • 2021-01-14 06:57

    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...
      }
    
    }
    
    0 讨论(0)
  • 2021-01-14 07:09

    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.

    0 讨论(0)
提交回复
热议问题