Kann eine Funktion einen von mehreren Typen zurückgeben, die keinen gemeinsamen Vorfahren haben?

8

Natürlich merke ich, dass alle Typen do einen gemeinsamen Vorfahren haben, aber was ich meine, ist dies:

In dynamisch typisierten Sprachen ist es üblich, gemischte Rückgabetypen zu verwenden. Ein häufiger Fall ist eine Funktion, die versucht, Daten aus einer Datenbank abzurufen, und dann entweder ein Objekt (initialisiert mit den gefundenen Daten) oder FALSE (falls keine Daten gefunden wurden) zurückgibt.

Ein kleiner Pseudocode, um ein solches Anti-Pattern zu demonstrieren:

%Vor%

Wenn Daten für meine Objekt-ID gefunden werden, bekomme ich einen DB-Datensatz als Objekt zurück. Wenn nicht, erhalte ich einen booleschen Wert. Dann liegt es natürlich an mir, dem Kunden, mehrere mögliche Rückgabetypen zu behandeln.

Ist das die einzige Möglichkeit, dies in Scala zu erreichen, um einen gemeinsamen Vorfahren für alle möglichen Rückgabetypen zu finden und dies als Rückgabetyp in der Signatur zu deklarieren?

%Vor%

Oder ist es möglich, mehrere mögliche Rückgabetypen zu kommentieren?

(Beachten Sie, dass ich nicht hoffe, ist es möglich, dies zu tun, da ich es vorziehen würde, dass Funktionsrückgabetypen so eindeutig wie möglich sind. Es würde mir eine Erleichterung sein zu lernen, dass die Sprache zweideutige Rückgabetypen verbietet, was mehr der Grund ist, warum ich frage.

    
Ben Wilhelm 19.01.2013, 01:39
quelle

3 Antworten

16

Was Sie suchen, ist eine markierte Vereinigung , Variante , abweichende Aufzeichnung , diskriminierte Vereinigung , disjoint union oder sum type .

Kombiniert mit Produkttypen werden sie zu algebraischen Datentypen .

Scala hat keine direkte Unterstützung für algebraische Datentypen, aber es muss nicht, weil sie leicht durch Vererbung modelliert werden können. (Scala hat den Modifizierer sealed , um geschlossene ADTs zu unterstützen.)

Wenn Sie in Ihrem Beispiel wissen, dass der Rückgabetyp entweder SomeType oder SomeOtherType ist, können Sie es wie folgt modellieren:

%Vor%

Wenn Sie nicht wissen, was die Rückgabetypen sind, nur dass es zwei davon gibt, können Sie sie ähnlich modellieren:

%Vor%

Dies ist ein bekannter Datentyp namens Either (weil er entweder ein A oder ein B enthält) und in der Scala-Standardbibliothek als scala.util.Either vorhanden ist.

Aber in Ihrem speziellen Fall gibt es einen spezifischeren Typ namens Maybe oder Option , der die Idee kapselt, dass ein Wert existiert oder nicht. Es sieht ungefähr so ​​aus:

%Vor%

Auch dies wird von Scala bereits als scala.Option bereitgestellt.

Der Vorteil von Either über Option ist, dass Sie auch Informationen im Fehlerfall zurückgeben können, anstatt nur anzugeben, dass es keinen Wert gibt. Sie können auch sagen, warum es keine gibt Wert. (Per Konvention ist die linke Seite von Either der Fehler, die rechte Seite ist der "nützliche" Wert.)

Der Vorteil von Option ist, dass es eine Monade ist. (Hinweis: Sie können Either zu einer Monade machen, indem Sie sie entweder nach links oder nach rechts vorbelasten.)

    
Jörg W Mittag 19.01.2013, 02:38
quelle
20

Ja, verwenden Sie Either :

%Vor%

Oder, wenn der Fall ohne Ergebnisse keinen bestimmten Wert benötigt, verwenden Sie Option :

%Vor%

Siehe Tony Morris ' Option-Spickzettel für eine Liste der gebräuchlichsten Methoden Sie können Option aufrufen und wie sie zum Mustervergleich übersetzt werden.

Zwei weitere Alternativen sind Validation von Scalaz und Try , neu in Scala 2.10.

Für Validation gibt es einige wirklich gute Antworten auf StackOverflow, zum Beispiel: Methode Parameter Validierung in Scala, mit Verständnis und Monaden .

Für Try siehe diesen Blogbeitrag: Der Leitfaden des Neophyten zu Scala Teil 6: Fehlerbehandlung mit Try . Derselbe Autor hat gute Beiträge auf Option und Either .

    
sourcedelica 19.01.2013 02:03
quelle
2

Wenn Sie zur Laufzeit wissen, nach welchem ​​Typ Sie in jedem Aufruf suchen, könnte Ihre Signatur wie folgt lauten:

%Vor%

Oder, um Ihre if / else Logik dort zu simulieren, würde ich Option hier empfehlen:

%Vor%

Beispielverwendung:

%Vor%     
7zark7 19.01.2013 02:02
quelle

Tags und Links