Scala: if-else到带有Option的声明性代码



我有一段scala代码作为(x包含几个Option字段):

x.y.flatMap(_.z).map {
z =>
someMethod(z) // for side effect
}.getOrElse {
if (condition) {
someOtherMethod() // for side effect
} else {
yetAntherMethod // for side effect
}
}

基本上,代码根据特定的条件执行不同的路径,就像命令式java代码中传统的if-else一样。

我想修改它,使其更具声明性,比如基于x中的某些字段执行不同的路径。

x.a defined then do A 
otherwise x.b defined then do B 
otherwise x.c defined do C..and so on

我无法编写流。

您可以按照以下方式组合流

val optionalValue = Option(1)
optionalValue match {
case Some(value) if value == 1 => A()
case Some(value) if value == 2 => B()
case Some(value) if value == 3 => C()
case None =>
}

基于@ccheneson的答案,您还可以使用解构模式匹配:

case class MyStruc(a: Option[String], b: Option[String], c: Option[String])
def doA(a: String): Unit = println(s"A: $a")
def doB(b: String): Unit = println(s"B: $b")
def doC(c: String): Unit = println(s"C: $c")
def main(args: Array[String]): Unit = {
def doIt(x: MyStruc) = {
x match {
case MyStruc(Some(a), _, _) => doA(a)
case MyStruc(_, Some(b), _) => doB(b)
case MyStruc(_, _, Some(c)) => doC(c)
case _ => ()
}
}
doIt(MyStruc(Some("1"), Some("2"), Some("3"))) // A: 1
doIt(MyStruc(None, Some("4"), Some("5")))      // B: 4
doIt(MyStruc(None, None, Some("6")))           // C: 6
doIt(MyStruc(None, None, None))                // no output
}

由于您的类似乎有几个Option,并且遵循您的伪代码,您可以使用模式匹配,如

case class MyStruc(a: Option[String], b: Option[String], c: Option[String])
val x = MyStruc(Some("1"), Some("2"), Some("3"))
x match {
case x.a if x.a.isDefined => doA(x.a.get) 
case x.b if x.b.isDefined => doB(x.b.get)
case x.c if x.c.isDefined => doA(x.c.get)
}

您可以使用isDefined来检查它是否为Some,如果是,则可以安全地调用.get

对于问题中的特定示例,最干净的解决方案是仅使用if/else:

if (x.y.flatMap(_.z).map(someMethod).isEmpty) {
if (condition) {
someOtherMethod()
} else {
yetAntherMethod()
}
}

链接Option值的更一般的情况可以使用orElse:

x.a.map(A) orElse
x.b.map(B) orElse 
x.c.map(C)

如果需要,可以使用Option.when将条件转换为Option

最新更新