Option Monade in scala
-
28-09-2019 - |
Frage
Wie wird Arbeit Option Monade gemeint? Ich bin das Surfen im scala api und es ist ein Beispiel (I die zweiten bedeuten),
Weil, wie für das Verständnis funktioniert, wenn kein von request.getParameter zurückgegeben wird, die gesamte Ausdruck Ergebnisse in None
Aber wenn ich versuche, diesen Code ein:
val upper = for {
name <- None //request.getParameter("name")
trimmed <- Some(name.trim)
upper <- Some(trimmed.toUpperCase) if trimmed.length != 0
} yield upper
println(upper.getOrElse(""))
Ich bekomme einen Compiler-Fehler. Wie soll das denn funktionieren?
Lösung
Sie einen Compiler-Fehler erhalten, weil dies
name <- None
Auf diese Weise wird die Art des None
zu None.type
gesetzt und die Variable name
wird abgeleitet vom Typ Nothing
sein. (Das heißt, würde es diese Art hat, wenn es existiert tatsächlich aber offensichtlich die für das Verständnis nicht einmal, um es zur Laufzeit zu schaffen.) Daher ist keine Methode name.trim
existiert, und es wird nicht kompiliert.
Wenn Sie request.getParameter("name")
zur Verfügung hätte, würde seine Art sein Option[String]
, name
würde möglicherweise Typ String
haben und name.trim
würde kompilieren.
Sie können dies umgehen, indem Sie die Art der None
Angabe:
name <- None: Option[String]
Andere Tipps
Um auf Kevins Antwort zu erweitern, Sie Verpackung Werte in Some()
unter Verwendung des =
Operator anstelle des <-
Betreiber vermeiden kann:
val upper = for {
name <- None: Option[String] //request.getParameter("name")
trimmed = name.trim
upper = trimmed.toUpperCase if trimmed nonEmpty
} yield upper
Das für Verständnis zu etwas sehr ähnlich zu Kevins Version kompilieren, aber wir finden es oft klarer map
und filter
explizit zu vermeiden Unordnung (zB zusätzliche Variablennamen) hinzufügen, dass nichts auf den semantischen Inhalt des Ausdrucks zu verwenden.
Um auf Debilski Antwort zu erweitern, Sie brauchen auch nicht explizit nachfolgende Werte in Some()
wickeln, der einzige Wert, sind Sie tatsächlich über die Abbildung ist die ursprüngliche name
.
Ein besserer Ansatz die map
und filter
Operationen direkt anstelle eines für Verständnis zu verwenden sein würde:
Hinweis: hinter den Kulissen wird der Scala-Compiler eines konvertieren für Verständnis auf eine Kombination von Karte / flatMap / Filter wie auch immer, so dass dieser Ansatz nie weniger effizient sein wird als ein für Verständnis und gut sein kann effiziente
def clean(x:Option[String]) = x map { _.trim.toUpperCase } filterNot { _.isEmpty }
val param = None : Option[String] // request.getParameter("name")
println( clean(param).getOrElse("") )