Scala - wertet Funktionsaufrufe der Reihe nach aus, bis eine zurückkommt

7

Ich habe ein paar "Legacy" -Endpunkte, die die gesuchten Daten zurückgeben können.

%Vor%
  • null kann zurückgegeben werden, wenn keine DataX gefunden
  • ist
  • Rückgabetypen für jede Methode sind unterschiedlich. Es gibt eine convert -Methode, die jedes DataX in ein einheitliches Data konvertiert.
  • Die Endpunkte sind nicht Scala-ish

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%     
Stas 08.11.2017, 10:28
quelle

5 Antworten

16

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

zurück %Vor%     
Ossip 31.12.2017, 04:25
quelle
5

Vielleicht können Sie diese Methoden als Funktionen höherer Ordnung von List s und collectFirst anheben, wie:

%Vor%     
chengpohi 08.11.2017 11:27
quelle
5

Der beste Scala-Ansatz IMHO ist, Dinge auf die einfachste Art zu tun.

  • Um optionale Werte (oder null s aus Java-Land) zu behandeln, verwenden Sie Option .
  • Um eine Liste von Methoden sequentiell auszuwerten, falten Sie über 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.

    1. ( Bearbeiten ) Implizite Konvertierungen vorausgesetzt:

      %Vor%
    2. ( Bearbeiten ) Verwenden expliziter Konvertierungen:

      %Vor%
g.krastev 03.01.2018 15:39
quelle
3

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

erhalten

(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.

    
Eugene Loy 30.12.2017 21:52
quelle
2

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:

%Vor%

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:

%Vor%

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 ):

%Vor%

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.

    
Nicolas Rinaudo 04.01.2018 12:39
quelle

Tags und Links