Warum ist unveränderlich Set Scala nicht in seiner Art kovariant?
-
21-08-2019 - |
Frage
Bearbeiten : Re-geschrieben, diese Frage anhand von Original-Antwort
Die scala.collection.immutable.Set
Klasse ist in seiner Art Parameter nicht kovariant. Warum ist das?
import scala.collection.immutable._
def foo(s: Set[CharSequence]): Unit = {
println(s)
}
def bar(): Unit = {
val s: Set[String] = Set("Hello", "World");
foo(s); //DOES NOT COMPILE, regardless of whether type is declared
//explicitly in the val s declaration
}
Lösung
Set
ist unveränderlich in seiner Art Parameter, weil das Konzept hinter Sätze als Funktionen. Die folgenden Signaturen sollten die Dinge klären leicht:
trait Set[A] extends (A=>Boolean) {
def apply(e: A): Boolean
}
Wenn Set
in A
kovariant wurden, wären die apply
Verfahren nicht in der Lage einen Parameter vom Typ A
nimmt aufgrund der Kontra von Funktionen. Set
könnte möglicherweise sein kontra in A
, aber auch dies verursacht Probleme, wenn Sie solche Dinge tun:
def elements: Iterable[A]
Kurz gesagt, die beste Lösung ist, die Dinge unveränderlich zu halten, auch für die unveränderliche Datenstruktur. Sie werden feststellen, dass immutable.Map
bemerken in einem seiner Art Parameter auch unveränderlich ist.
Andere Tipps
http://www.scala-lang.org/node/9764 Martin Odersky schreibt:
„In der Frage der Sätze, ich die Nicht-Varianz ergibt sich auch aus den Implementierungen glauben. Sind häufig Sätze wie Hash-Tabellen implementiert, die nicht-Variante Arrays der Schlüsseltyp sind. Ich bin damit einverstanden, es ist ein wenig ärgerlich Unregelmäßigkeit.“
So scheint es, dass alle unsere Bemühungen, einen prinzip Grund dafür waren fehlgeleitet zu konstruieren: -)
Bearbeiten : für fragen, jemand, warum diese Antwort ein wenig vom Thema scheint, ist dies, weil ich (der Fragesteller) die Frage geändert haben.
Scala Typinferenz ist gut genug, um herauszufinden, dass Sie CharSequences und nicht Strings in einigen Situationen wollen. Insbesondere die folgenden Werke für mich in 2.7.3:
import scala.collections.immutable._
def findCharSequences(): Set[CharSequence] = Set("Hello", "World")
Wie, wie immutable.HashSets direkt zu erstellen: dies nicht tun. Als umsetzungs Optimierung, immutable.HashSets von weniger als 5 Elemente sind nicht wirklich Instanzen immutable.HashSet. Sie sind entweder emptyset, Set1, Set2, Set3 oder Set4. Diese Klassen Unterklasse immutable.Set, aber nicht immutable.HashSet.