Das ist etwas, worüber ich mich schon eine Weile gewundert habe. Ich sehe dieses Muster eine Menge:Ist das PartialFunction-Design ineffizient?
if (pf.isDefinedAt(in)) pf(in)
Durch diese Zerschlagung in zwei getrennte Anrufe, alle Muster, die in #isDefinedAt ausgewertet wurden, werden dann auch in #apply ausgewertet. Zum Beispiel:
object Ex1 {
def unapply(in: Int) : Option[String] = {
println("Ex1")
if (in == 1) Some("1") else None
}
}
object Ex2 {
def unapply(in: Int) : Option[String] = {
println("Ex2")
if (in == 2) Some("2") else None
}
}
val pf : PartialFunction[Int,String] = {
case Ex1(result) => result
case Ex2(result) => result
}
val in = 2
if (pf.isDefinedAt(in)) pf(in)
Welche druckt
Ex1
Ex2
Ex1
Ex2
res52: Any = 2
Im schlimmsten Fall, wo Ihr Muster letzten Spiele, haben Sie Ihre Muster/Extraktoren zweimal ausgewertet, wenn eine Partielle Funktion aufrufen. Dies könnte beim Abgleich über benutzerdefinierte Extraktoren, die mehr als nur eine einfache Klassen- oder Listenmusterübereinstimmung aufwiesen, ineffizient werden (z. B. wenn Sie einen Extraktor hatten, der ein XML-Dokument analysierte und einige Wertobjekte zurückgab)
PartialFunction # lift leidet die gleiche Doppelauswertung:
scala> pf.lift(2)
Ex1
Ex2
Ex1
Ex2
res55: Option[String] = Some(2)
gibt es eine Möglichkeit bedingt eine Funktion aufzurufen, wenn es zweimal ohne potenziell ruft alle Ihre Extraktoren definiert ist?
Vielen Dank für die ausführliche Antwort! FunctionWithDefault klingt genau nach dem was ich gesucht habe. – Collin
Zweimal richtiges Pattern-Matching ist ein großer Performance-Hit, wenn Sie komplexe Match-Anweisungen in performancekritischem Code haben! Und wenn 'default' mit Namen übergeben wird, wie soll das effizienter sein als eine Option zurückgeben? Vielleicht sollte ich scala-internals lesen. –
Ich habe das sig-default falsch, eher bizarr ist es ein 'I => OO' –