Der Scala Optionstyp ist der Schlüssel für den Umgang mit Variablen, die Werte haben können oder nicht. Die meisten Bibliotheken und Anwendungen machen von diesem praktischen Typ Gebrauch. Allerdings kann seine Verwendung in bestimmten Fällen zu recht umständlichem Code führen. In diesem Blog erfahren Sie, wie Sie diesen speziellen Fall mit Hilfe von Implicits auf elegante Weise lösen können. Lesen Sie weiter, um zu sehen, wie einfach es ist, jede Art von bestehendem Scala-Typ anhand eines Beispiels mit Options perfekt an Ihre Bedürfnisse anzupassen.
Ich liebe den Typ Option in Scala. Optionen bieten eine sehr prägnante Möglichkeit, auszudrücken, ob eine Variable einen Wert haben kann oder nicht. Während ein Programmierer seine Absicht in Scala auf äußerst prägnante und kompakte Weise ausdrücken kann, muss ich zugeben, dass dies beim Umgang mit Optionen nicht immer der Fall ist.
val myOpt:Option[Int] = Some(1234)
val converted = myOpt match {
case Some(v) => v.toString.reverse.mkString("-")
case None => "unknown"
}
assert("4-3-2-1" == converted)
Was wir hier erreichen wollen, ist im Grunde eine Konvertierung von Int in einen String, je nachdem, ob die Option vom Typ Some(Int) ist. Andernfalls möchten wir den Standardwert "Unbekannt" verwenden.
Dies ist der einzige Fall, der mir einfällt, in dem ich Scala mit Kesselsteincode in Verbindung bringen kann. Vier Zeilen Code, um eine einfache Konvertierung durchzuführen oder einen Standardwert bereitzustellen, je nachdem, ob wir es mit einem Some oder None zu tun haben, ist ziemlich viel. Die gute Nachricht ist, dass es eine Alternative gibt. Durch die Verwendung anderer Methoden der Option API könnte ich dies wie folgt in einen Einzeiler umwandeln:
val myOpt:Option[Int] = Some(1234)
val converted = if(myOpt.isDefined) myOpt.get.toString.reverse.mkString("-") else "unknown"
assert("4-3-2-1" == converted)
Offensichtlich ist es gar nicht so schwer, die gewünschte Umwandlung in eine einzige Codezeile zu packen, aber die Verwendung von bedingter Logik, um das gewünschte Ergebnis zu erzielen, dämpft meine Begeisterung erheblich. Was ich eigentlich möchte, ist Folgendes:
val myOpt:Option[Int] = Some(1234)
val converted = myOpt some? (.toString.reverse.mkString("-")) orNone "unknown"
assert("4-3-2-1" == converted)
Ich persönlich fände eine solche API für Option sehr intuitiv zu bedienen, prägnant, kompakt und vollständig OO. Da es sie also (noch) nicht gibt, müssen wir uns selbst eine Lösung einfallen lassen. Da wir einem bestehenden Typ neue Funktionen hinzufügen möchten, ohne den Quellcode zu ändern, ist der Weg über Implikate zu gehen. Eine mögliche Lösung sieht wie folgt aus:
implicit def fromOptionToConvertedValT = new {
def some?[R] (doWithSomeVal:(T) => R) = new {
def orNone(handleNone: => R) = o match {
case Some(value) => doWithSomeVal(value)
case None => handleNone
}
}
}
Was geschieht hier? Wir definieren zunächst eine implizite Funktion, die eine Option als Parameter annimmt. Die Konvertierung gibt ein anonymes Objekt zurück, das eine Funktion mit dem Namen some? enthält. Natürlich kann jeder Name verwendet werden. Die some ? Funktion ist eine Funktion höherer Ordnung, die einen Funktionsparameter vom Typ T annimmt, der mit dem der Option identisch ist. Der Funktionsparameter von irgendeiner ? gibt dann einen neuen Typ von R zurück, da wir den Anfangswert vom Typ T in R umwandeln wollen.
Anstatt etwas innerhalb des Funktionskörpers zu tun, geben wir ein weiteres anonymes Objekt mit dem Gegenstück von irgendeinem? genannt orNone. Die Funktion orNone nimmt ein Call-by-Name-Argument entgegen. Der Körper von orNone erledigt die eigentliche Arbeit. Je nachdem, ob es sich bei der Option um ein Some handelt, wird der Funktionsparameter von some ? ausgeführt, andernfalls wird das Call-by-Name-Argument des orNone ausgeführt, was zum gewünschten Ergebnis führt.
Fazit: Wenn Sie in einer Bibliothek, die Sie in Scala verwenden, etwas vermissen, bieten Ihnen Implicits die perfekte Möglichkeit, alles hinzuzufügen, was Ihnen gefällt, so dass es für Sie funktioniert. Das ist die wahre 'Option', die Scala Ihnen bietet ;-)
Verfasst von

Urs Peter
Unsere Ideen
Weitere Blogs
Contact



