Wie funktioniert orElse arbeiten auf PartialFunctions
Ich bin immer sehr bizarres Verhalten (zumindest so scheint es mir) mit der orElse
Methode definiert PartialFunction
Es scheint mir, dass:
val a = PartialFunction[String, Unit] {
case "hello" => println("Bye")
}
val b: PartialFunction[Any, Unit] = a.orElse(PartialFunction.empty[Any, Unit])
a("hello") //"Bye"
a("bogus") //MatchError
b("bogus") //Nothing
b(true) //Nothing
macht Sinn, aber das ist nicht, wie es sich verhält, und ich habe eine Menge von Schwierigkeiten zu verstehen, warum die Arten Unterschriften scheinen zu zeigen, was ich ausgesetzt oben.
Hier ist ein Transkript von dem, was ich beobachte mit Scala 2.11.2:
Welcome to Scala version 2.11.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_11).
Type in expressions to have them evaluated.
Type :help for more information.
scala> val a = PartialFunction[String, Unit] {
| case "hello" => println("Bye")
| }
a: PartialFunction[String,Unit] = <function1>
scala> a("hello")
Bye
scala> a("bye")
scala.MatchError: bye (of class java.lang.String)
at $anonfun$1.apply(<console>:7)
at $anonfun$1.apply(<console>:7)
at scala.PartialFunction$$anonfun$apply$1.applyOrElse(PartialFunction.scala:242)
at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:36)
... 33 elided
scala> val b = a.orElse(PartialFunction.empty[Any, Unit])
b: PartialFunction[String,Unit] = <function1>
scala> b("sdf")
scala.MatchError: sdf (of class java.lang.String)
at $anonfun$1.apply(<console>:7)
at $anonfun$1.apply(<console>:7)
at scala.PartialFunction$$anonfun$apply$1.applyOrElse(PartialFunction.scala:242)
at scala.PartialFunction$OrElse.apply(PartialFunction.scala:162)
... 33 elided
Hinweis: der return-Typ von val b
denen nicht erweitern den Typ des PartialFunction.
Aber das funktioniert auch nicht wie erwartet:
scala> val c = a.orElse(PartialFunction.empty[String, Unit])
c: PartialFunction[String,Unit] = <function1>
scala> c("sdfsdf")
scala.MatchError: sdfsdf (of class java.lang.String)
at $anonfun$1.apply(<console>:7)
at $anonfun$1.apply(<console>:7)
at scala.PartialFunction$$anonfun$apply$1.applyOrElse(PartialFunction.scala:242)
at scala.PartialFunction$OrElse.apply(PartialFunction.scala:162)
... 33 elided
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gibt es ein paar Dinge, die falsch mit Ihrem Versuch, aber zuerst wollen wir sehen, eine funktionierende Implementierung:
Gibt es zwei wesentliche Fehler in deinem code:
empty
ist eine "catch-all" - Funktion, die zurückNothing
1. Wie definieren Sie einen PartialFunction
Wie nicht, Sie zu definieren:
Wenn man sich die definition von
PartialFunction.apply
du wirst sehen, dass es definiert eine partielle Funktion für alle
x
und es gilt die angegebenef
- Funktion. Jetzt ist Ihre{ case "hello" => println("bye") }
ist dief
argument, so dass Sie etwa am Ende mit den folgenden (natürlich unerwartet)PartialFunction
:So, wenn Sie Sie Fragen, ob es definiert ist, es wird immer true zurück, da es definiert für alle string:
aber wenn Sie versuchen, um
apply
eskurz auf die innere match.
Seit
orElse
entscheidet, ob Sie zum aufrufen der "andere" je nach Ergebnis derisDefined
, dann ist es offensichtlich, warum es scheitert.2. Leer, fängt nichts!
Direkt aus der docs:
Den
PartialFunction
(gut, es ist nicht wirklich teilweise mehr), die Sie suchen:oder - nur um zu zeigen, dass wir aus unseren Fehlern lernen -
c
PartialFunction[String, Unit]
stattPartialFunction[Any, Unit]
?orElse
sollte es eigentlich ablehnenb
als parameter, daAny
ist kein Subtyp vonString
. Es irgendwie behandeltb
alsPartialFunction[String, Unit]
und macht es Arbeit. Jedenfalls ist der zurückgegebene Typ vonorElse
wird nie breiter als die original-Funktionen zusammengesetzt ist.orElse
sollte auf jeden Fall ablehnenb
. Ich habe eine Frage gestellt, mal sehen, ob jemand dies herauszufinden: stackoverflow.com/questions/25394557/...Sind Sie mit der
PartialFunction
Objekt Methode anwenden, die ist so definiert:Grundsätzlich dauert es eine Funktion, form
A
zuB
automatisch und wickeln Sie es in eine case-Anweisung, das problem ist, dass Sie auf der Durchreise sind, den Fall zu und ich bin nicht 100% sicher was dann passiert, können Sie versuchen, übergeben Sie eine Funktion anwenden oder einfach können Sie versuchen, ohne mithilfe der apply-Methode:Könnte man auch erweitern, um das Merkmal zu implementieren
apply
undisDefined
wie gezeigt hier.PartialFunction.empty[A,B]
ist äquivalent zu:(Diese typechecks, weil
Nothing
ist ein Subtyp der beidenA
undB
.)oder, was dasselbe ist:
Diese nicht mit etwas.
.orElse
verstanden werden können einfach verkettet Listen von case-Anweisungen von zweiPartialFunction
s. Also, in deinem Falla.orElse(PartialFunction.empty[Any,Unit]
bedeutet:vereinfacht zu:
oder
MatchError
ist also offensichtlich.Beachten Sie, dass die documetation auch erwähnt, dass
empty
wirft immerMatchError
.Aus dem, was ich denke, Sie wollte ein
PartialFunction
dass immer passt. Es gibt keine Methode mit dem Namen in der standard-Bibliothek für die, aber warum sollte es. Sie können einfach schreibenval b: PartialFunction[String, Unit] = a.orElse(PartialFunction[String, Unit] { case _ => println("123") })
bekomme ich noch passen Ausnahme mache ich, wenn ichb("123")
, ja, ich glaube, Sie haben Recht, dassPartialFunction.empty
entsprichtNothing
.MatchError
passiert, bevorb
wie bereits in meinem Kommentar gibt es keine übereinstimmung aufNothing
weil ich bin nicht mitPartialFunction.empty
mehr, ich habe zwei separate PF, eine, die passt"hello"
und die andere, die Spiele_
.a
ist schlecht definiert und das ist, wo das Problem Auftritt.