Wie funktioniert orElse bei PartialFunctions?

8

Ich bekomme sehr seltsames Verhalten (zumindest scheint es mir) mit der Methode orElse , die für PartialFunction

definiert wurde

Es scheint mir so:

%Vor%

macht Sinn, aber das ist nicht so, wie es sich verhält, und ich habe große Schwierigkeiten zu verstehen, warum die Typenunterschriften darauf hindeuten, was ich oben dargelegt habe.

Hier ist eine Abschrift von dem was ich mit Scala 2.11.2:

beobachte %Vor%

Beachten Sie den Rückgabetyp von val b , der den Typ der PartialFunction nicht erweitert hat.

Aber das funktioniert auch nicht wie erwartet:

%Vor%     
jedesah 18.08.2014, 21:48
quelle

3 Antworten

26

Es gibt ein paar Dinge, die mit Ihrem Versuch nicht stimmen, aber lassen Sie uns zuerst eine funktionierende Implementierung sehen:

%Vor%

Es gibt zwei Hauptfehler in Ihrem Code:

  1. wie der PF definiert ist
  2. die (falsche) Annahme, dass empty eine "catch-all" -Funktion ist, die Nothing zurückgibt

1. Wie definiere ich eine PartialFunction

%Vor%

Wie nicht um es zu definieren:

%Vor%

Wenn Sie sich die Definition von PartialFunction.apply

ansehen %Vor%

Sie sehen, dass es eine Teilfunktion für any x definiert und die angegebene f -Funktion darauf anwendet. Jetzt ist Ihr { case "hello" => println("bye") } das Argument f , so dass Sie ungefähr mit dem folgenden (eindeutig unerwarteten) PartialFunction :

enden %Vor%

Wenn Sie also fragen, ob es definiert ist, wird immer true zurückgegeben, da es für any definiert ist:

%Vor%

Aber wenn Sie versuchen, apply it

%Vor%

Sie treffen das innere Spiel nicht.

Da orElse entscheidet, ob das "else" abhängig vom Ergebnis von isDefined aufgerufen werden soll, ist es offensichtlich, warum es fehlschlägt.

2. Leer fängt nichts!

Direkt von den Dokumenten :

  

def empty[A, B]: PartialFunction[A, B]

     

Die Teilfunktion mit leerer Domain. Jeder Versuch, eine leere Teilfunktion aufzurufen, führt dazu, dass scala.MatchError exception ausgelöst wird.

Das PartialFunction (naja, es ist nicht wirklich partiell), das du suchst, ist:

%Vor%

oder - nur um zu zeigen, dass wir aus unseren Fehlern lernen -

%Vor%     
Gabriele Petronella 18.08.2014, 23:11
quelle
1

PartialFunction.empty[A,B] entspricht:

%Vor%

(Diese Typprüfung, weil Nothing ein Untertyp von A und B ist.)

oder äquivalent:

%Vor%

Dies kann nichts erreichen.

.orElse kann so verstanden werden, dass Listen von case-Anweisungen von zwei PartialFunction s einfach verkettet werden. Also, in Ihrem Fall bedeutet a.orElse(PartialFunction.empty[Any,Unit] :

%Vor%

vereinfacht das:

%Vor%

oder

%Vor%

MatchError ist daher offensichtlich.

Beachten Sie, dass die Dokumentation auch immer empty erwähnt wirft MatchError .

Von dem, was ich erraten kann, wollten Sie ein PartialFunction , das immer übereinstimmt. Dafür gibt es keine benannte Methode in der Standardbibliothek, aber warum sollte es da sein? Sie können einfach

schreiben %Vor%     
Karol S 18.08.2014 22:22
quelle
1

Sie verwenden die Methode PartialFunction object apply, die so definiert ist:

%Vor%

Im Grunde nimmt es eine Funktionsform A bis B und wickelt es automatisch in eine case-Anweisung, das Problem ist, dass Sie auch den Fall übergeben und ich bin nicht 100% sicher, was dann passiert, können Sie Versuchen Sie, eine Funktion an die Anwendung zu übergeben, oder Sie können es einfach ausprobieren, ohne die Methode apply zu verwenden:

%Vor%

Sie können das Merkmal auch erweitern und apply und isDefined implementieren, wie gezeigt. hier .

    
Ende Neu 18.08.2014 22:22
quelle