Warum funktioniert Map/Filter… nicht mit einer Reihe von nichts?
-
27-10-2019 - |
Frage
Ist nichts nichts von allen Typen?
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)
^
Es ist seltsam, dass dies nicht funktioniert.
Ist dies angegeben, eine Funktion oder ein Fehler?
Lösung
Wenn Sie ein seltsames Verhalten mit nichts sehen, liegt es daran, dass der Typ -Inferenz -Algorithmus der Meinung ist, dass er nichts selbst eingefügt hat, da er während des Typs Inferenz eingeführt wird: Wenn nichts über eine Typvariable bekannt ist, dann wird es von irgendeiner und nichts begrenzt. Es ist seit langem auf meiner Liste der Dinge, die zu tun sind, um zu sehen, ob ich für diesen Zweck einen neuen internen Bottom-Typ einführen kann, damit nichts, was nichts mit dem Benutzer auf Inferenzebene aufnimmt, nicht vermischt ist, aber es ist eine ziemlich ehrgeizige Aufgabe. Trotzdem könnte ich jetzt hardcore genug sein, um es zu versuchen.
Andere Tipps
Ich vermute, Scala sollte Sie nicht so machen lassen Array[Nothing]
Instanziierung. Es gibt per Definition keine Fälle von nichts in der Nähe, aber Ihr Array sieht so aus, als wäre es gefüllt Nothing
s, die null sind, aber Null ist kein gültiger Wert für Nothing
. Dies schlägt beispielsweise mit dem Fehler fehl type mismatch; found : Null(null) required: Nothing
val n: Nothing = null
Ich würde also erwarten, jedes Mal, wenn Sie das System täuschen können, in Schwierigkeiten zu kommen, um zu glauben Nothing
…
Hier ist ein weiterer seltsamer Fall. Führen Sie das aus:
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...
}
}
Beachten Sie, dass der Skala -Array -Typ invariant ist. So Nothing
Ein Subtyp von allem zu sein, ist möglicherweise nicht relevant.
Ebenfalls map
und filter
sind nicht definiert auf Array
. Implizite Konvertierungen in Predef
werden verwendet, um solche Methoden für Arrays bereitzustellen.
Daher kann der Compiler keine implizite Konvertierung finden Array[Nothing]
zu etwas, das das hat map
oder filter
definiert. Mit der Reply kann ich tatsächlich sehen, dass eine solche implizite Konvertierung verfügbar sein sollte:
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)
Die Frage lautet also, warum der Compiler das nicht berücksichtigt genericArrayOps
Wandlung.