Scala Option-Objekt in einem anderen Option-Objekt

7

Ich habe ein Modell, das einige Optionsfelder enthält, die weitere Optionsfelder enthalten. Zum Beispiel:

%Vor%

Ich erhalte diese Daten von externen JSONs und manchmal enthalten diese Daten möglicherweise Nullen, das war der Grund für einen solchen Modellentwurf.

Die Frage ist also: Was ist der beste Weg, um ein tiefstes Feld zu bekommen?

%Vor%

Die obige Methode sieht wirklich hässlich aus und es kann eine Ausnahme verursachen, wenn eines der Objekte None ist. Ich habe nach Scalaz Lib gesucht, aber ich habe keinen besseren Weg gefunden, das zu tun.

Irgendwelche Ideen? Vielen Dank im Voraus.

    
psisoyev 27.02.2013, 11:59
quelle

4 Antworten

15

Die Lösung besteht darin, Option.map und Option.flatMap zu verwenden:

%Vor%

Oder das Äquivalent (siehe update am Ende dieser Antwort):

%Vor%

Dies gibt Option[Int] zurück (vorausgesetzt, dass numberOfSmth ein Int zurückgibt). Wenn eine der Optionen in der Aufrufkette None ist, lautet das Ergebnis None , andernfalls wird Some(count) angegeben, wobei count der von numberOfSmth zurückgegebene Wert ist.

Natürlich kann das sehr schnell hässlich werden. Aus diesem Grund unterstützt scala für Comprehensions als syntaktischen Zucker. Das obige kann wie folgt umgeschrieben werden:

%Vor%

Was wohl netter ist (besonders, wenn Sie noch nicht gewohnt sind, map / flatMap überall zu sehen, wie es sicherlich nach einer Weile mit scala der Fall ist), und generiert genau den gleichen Code unter der Haube.

Für weitere Hintergrundinformationen können Sie diese andere Frage überprüfen: Was ist Scalas Ausbeute?

UPDATE : Danke an Ben James für den Hinweis, dass flatMap assoziativ ist. Mit anderen Worten: x flatMap(y flatMap z))) ist identisch mit x flatMap y flatMap z . Letzteres ist zwar in der Regel nicht kürzer, hat aber den Vorteil, dass eine Verschachtelung vermieden wird, die leichter nachvollziehbar ist.

Hier ist ein Beispiel in der REPL (die 4 Stile sind äquivalent, wobei die ersten beiden die flatMap-Verschachtelung verwenden, die anderen beiden flache Ketten von flatMap verwenden):

%Vor%     
Régis Jean-Gilles 27.02.2013, 12:05
quelle
10

Scalaz ist nicht nötig:

%Vor%

Alternativ können Sie verschachtelte FlatMaps

verwenden     
om-nom-nom 27.02.2013 12:03
quelle
4

Dies kann durch Verketten von Aufrufen an flatMap :

erfolgen %Vor%

Sie können dies auch mit einem Verständnis machen, aber es ist ausführlicher, da es Sie zwingt, jeden Zwischenwert zu benennen:

%Vor%     
Ben James 27.02.2013 12:03
quelle
0

Ich denke, es ist ein Overkill für Ihr Problem, aber nur als allgemeine Referenz:

Dieses verschachtelte Zugriffsproblem wird durch ein Konzept namens Objektive behoben. Sie bieten einen guten Mechanismus für den Zugriff auf verschachtelte Datentypen durch einfache Komposition. Als Einführung sollten Sie beispielsweise nach dieser SO-Antwort oder dieses tutorial . Die Frage, ob es sinnvoll ist, Objektive in Ihrem Fall zu verwenden, ist, ob Sie in Ihrer geschachtelten Optionsstruktur auch viele Aktualisierungen vornehmen müssen (Hinweis: update nicht im veränderbaren Sinne, sondern eine neue modifizierte aber unveränderliche Instanz). Ohne Linsen führt dies zu einer langen verschachtelten Fallklasse copy code. Wenn Sie überhaupt nicht updaten müssen, würde ich den Vorschlag von om-nom-nom einhalten.

    
bluenote10 27.02.2013 12:04
quelle

Tags und Links