Ich möchte etwas Logik ausführen, wenn der Wert einer Option festgelegt ist.
Ich kam aus einem Java-Hintergrund:
%Vor%Wenn ich ein bisschen weiter in scala gehe, kann ich das schreiben als:
%Vor%Welcher ist besser? Die "foreach" klingt mehr "idiomatisch" und weniger Java, aber es ist weniger lesbar - "foreach", das auf einen einzelnen Wert angewendet wird, klingt seltsam.
Ihr Beispiel ist nicht vollständig und Sie verwenden keine minimale Syntax. Vergleichen Sie einfach diese zwei Versionen:
%Vor%und
%Vor% In beiden Versionen gibt es mehr syntaktischen Overhead in der if
-Lösung, aber ich stimme zu, dass foreach
auf einem Option
verwirrend sein kann, wenn Sie es nur als optionalen Wert betrachten.
Stattdessen beschreibt foreach
, dass Sie irgendeine Art von Nebenwirkungen machen wollen, was sehr sinnvoll ist, wenn Sie denken, dass Option
eine Monade ist und foreach
nur eine Methode, um sie zu transformieren. Die Verwendung von foreach
hat außerdem den großen Vorteil, dass es das Refactoring einfacher macht - Sie können einfach seinen Typ in List
oder eine andere Monade ändern und Sie erhalten keine Compilerfehler (wegen der großen Collections-Bibliothek von Scalas, auf die Sie nicht angewiesen sind Verwenden Sie nur Operationen, die auf Monaden funktionieren, es gibt viele Methoden, die für viele Typen definiert sind.)
foreach
ist sinnvoll, wenn Sie Option
als eine Liste betrachten, die höchstens einen einzelnen Wert enthalten kann. Dies führt auch zu einer korrekten Intuition über viele andere Methoden, die für Option
verfügbar sind.
Ich kann mir mindestens einen wichtigen Grund vorstellen, warum Sie foreach
in diesem Fall bevorzugen sollten: Es beseitigt mögliche Laufzeitfehler. Mit dem nonEmpty
-Ansatz müssen Sie an einem Punkt ein get
* machen, was Ihr Programm spektakulär zum Absturz bringen kann, wenn Sie versehentlich vergessen, einmal nach Leerheit zu suchen.
Wenn du get
komplett aus deinem Verstand löschst, um Fehler dieser Art zu vermeiden, ist ein Nebeneffekt, dass du weniger Nutzen für nonEmpty
hast! Und Sie werden anfangen, foreach
zu genießen und sich vom Compiler kümmern zu lassen, was geschehen soll, wenn Option
leer ist.
Sie werden sehen, dass dieses Konzept an anderen Orten auftaucht. Du würdest es nie tun
%Vor%Was Sie lieber sehen werden, ist
%Vor% Das Prinzip ist, dass Sie vermeiden wollen, dass Sie Code schreiben müssen, der den Fehlerfall behandelt - Sie möchten diese Last auf den Compiler übertragen. Viele werden Ihnen sagen, dass Sie niemals get
verwenden sollten, egal wie vorsichtig Sie denken, dass Sie vor der Überprüfung sind. Das macht die Dinge einfacher.
* Es sei denn, Sie möchten nur wissen, ob Option
einen Wert enthält und nicht wirklich nach dem Wert interessiert. In diesem Fall ist nonEmpty
in Ordnung. In diesem Fall dient es als eine Art toBoolean
.
Dinge, die ich in den anderen Antworten nicht gefunden habe:
Wenn ich if
verwende, bevorzuge ich if (opt isDefined)
bis if (opt nonEmpty)
, da ersteres weniger sammlungähnlich ist und es klarer macht, dass es sich um eine Option handelt, aber das kann Geschmackssache sein .
if
und foreach
unterscheiden sich in dem Sinne, dass if
ein Ausdruck ist, der einen Wert zurückgibt, während foreach
Unit
zurückgibt. In gewisser Weise ist die Verwendung von foreach
sogar noch Java-ähnlicher als if
, da Java eine foreach-Schleife hat und Java if
kein Ausdruck ist. Verwenden Sie ein für das Verständnis ist mehr scala-like.
Sie können auch Mustervergleiche verwenden (dies ist aber auch weniger idiomatisch)
Sie können die Methode fold
verwenden, die zwei Funktionen benötigt, damit Sie einen Ausdruck im Fall Some
und einen anderen im Fall None
auswerten können. Möglicherweise müssen Sie den erwarteten Typ explizit angeben, da die Art der Inferenz funktioniert (wie in hier ). Meiner Meinung nach kann es manchmal noch klarer sein, entweder Mustererkennung oder val result = if (opt isDefined) expression1 else expression2
zu verwenden.
Wenn Sie keinen Rückgabewert benötigen und wirklich nicht mit dem nicht definierten Fall umgehen müssen, können Sie foreach
verwenden.
Tags und Links scala