Ich habe ein paar "Legacy" -Endpunkte, die die gesuchten Daten zurückgeben können.
%Vor%null
kann zurückgegeben werden, wenn keine DataX
gefunden convert
-Methode, die jedes DataX
in ein einheitliches Data
konvertiert. Was ist der beste Scala-Ansatz , um diese Methodenaufrufe der Reihe nach auszuwerten, bis ich den Wert habe, den ich brauche?
In pseudo würde ich etwas tun wie:
%Vor% Ich würde einen einfacheren Ansatz verwenden, obwohl die anderen Antworten ausführlichere Sprachfunktionen verwenden.
Verwenden Sie einfach Option()
, um die null
zu fangen, und ketten Sie mit orElse
. Ich nehme die Methoden convertX(d:DataX):Data
für die explizite Konvertierung an. Da es nicht gefunden werden kann, geben wir Option
Der beste Scala-Ansatz IMHO ist, Dinge auf die einfachste Art zu tun.
null
s aus Java-Land) zu behandeln, verwenden Sie Option
. Seq
der Funktionen. Um von einem Datentyp in einen anderen zu konvertieren, verwenden Sie entweder (1.) implizite Konvertierungen oder (2.) reguläre Funktionen, abhängig von der Situation und Ihren Vorlieben.
( Bearbeiten ) Implizite Konvertierungen vorausgesetzt:
%Vor%( Bearbeiten ) Verwenden expliziter Konvertierungen:
%Vor%Hier ist ein Weg, es zu tun.
(1) Sie können Ihre convert
-Methoden der Einfachheit halber implizit machen (oder sie in implizite Wrapper umbrechen).
(2) Verwenden Sie dann Stream
, um chain
aus Methodenaufrufen zu erstellen. Sie sollten der Typinferenz einen Hinweis geben, dass Ihr Stream Data
-Elemente enthalten soll (nicht DataX, wie von Legacy-Methoden zurückgegeben), damit das entsprechende implizite convert
auf jedes Ergebnis eines Legacy-Methodenaufrufs angewendet wird.
(3) Da Stream
faul ist und seinen Schwanz "nach Namen" auswertet, wird nur die erste Methode aufgerufen. An dieser Stelle können Sie einen trägen Filter anwenden, um null
Ergebnisse zu überspringen.
(4) Nun können Sie tatsächlich chain
auswerten, indem Sie das erste nicht null
Ergebnis mit headOption
(HACK) Leider ist die Skalatyp-Inferenz (zum Zeitpunkt des Schreibens, v2.12.4) nicht stark genug, um #::
stream-Methoden zu verwenden, es sei denn, Sie führen sie bei jedem Schritt der Weg. Die Verwendung von cons
macht Schlussfolgerung glücklich, ist aber umständlich. Außerdem ist das Erstellen des Streams mit der Methode vararg apply
des Companion-Objekts ebenfalls keine Option, da scala noch keine Varargs "von Name" unterstützt. In meinem Beispiel verwende ich die Kombination von stream
und toLazyData
Methoden. stream
ist ein generischer Helfer, baut Streams von 0-arg-Funktionen. toLazyData
ist eine implizite "Umwandlung nach Name", die für die Interaktion mit impliziten convert
-Funktionen, die von DataX
in Data
konvertieren, entworfen wurde.
Hier ist die Demo, die die Idee mit mehr Details demonstriert:
%Vor%Dies druckt:
%Vor% Hier maybeMyDataInEndpoint1
gibt null
zurück und maybeMyDataInEndpoint2
muss aufgerufen werden, wobei DataB
, maybeMyDataInEndpoint3
niemals aufgerufen wird, da wir bereits das Ergebnis haben.
Ich denke, @ g.krastev's Antwort ist perfekt für Ihren Anwendungsfall und Sie sollten das akzeptieren. Ich gebe nur ein wenig darauf hin, um zu zeigen, wie du den letzten Schritt mit Katzen etwas besser machen kannst.
>Zuerst das Muster:
%Vor%Dies ist im Grunde, was Sie haben, in einer Weise, dass Sie in die REPL kopieren und einfügen und kompilieren können.
Nun erklären wir zuerst, wie Sie jeden Ihrer Endpunkte in etwas Sicheres und Uneinheitliches verwandeln:
%Vor% Damit können Sie zum Beispiel Folgendes aufrufen, um maybeMyDataInEndpoint1
in ein UUID => Option[A]
zu verwandeln:
Die Idee besteht nun darin, Ihre Endpunkte in eine Liste von UUID => Option[A]
zu verwandeln und diese Liste zu falten. Hier ist Ihre Liste:
Sie können nun manuell falten, was @ g.krastev getan hat:
%Vor% Wenn Sie mit einer cats
-Abhängigkeit zufrieden sind, ist die Vorstellung, eine Liste von Optionen zu falten, nur ein konkreter Anwendungsfall eines gemeinsamen Musters (die Interaktion von Foldable
und Monoid
):
Es gibt noch andere Möglichkeiten, dies noch schöner zu machen, aber sie könnten in diesem Zusammenhang übertrieben sein - ich würde wahrscheinlich eine Typklasse deklarieren, um jeden Typ in ein Data
umzuwandeln, um makeSafe
einen saubereren Typ zu geben Unterschrift.
Tags und Links scala