我正在看下面的代码片段。当map-getOrElse和嵌套模式匹配在代码中增加时,它看起来不那么优雅。你有什么更好的选择吗?
case MyMessage =>
val image = (request \ "image").asOpt[String]
image.map { im =>
val conf = (request \ "confirmation").asOpt[String]
conf.map { cf =>
//code to retrieve ride
ride match {
case Some(r) =>
if (booleanCondition) sender ! SuccessCommand(JsBoolean(true), command)
else sender ! FailureCommand("Problem updating", command)
case None => sender ! FailureCommand("Ride empty", command)
}
} getOrElse (sender ! FailureCommand("Missing number", command))
} getOrElse (sender ! FailureCommand("Missing image", command))
答案 0 :(得分:2)
每当您使用生成Option的函数映射Option时,您应该考虑是否应该使用flatMap
:
def f(x: Int): Option[Int] = Some(x + 1)
f(1).flatMap(x => f(x)).flatMap(y => f(y)) // Some(4)
f(1).flatMap(x => f(x)).flatMap(y => f(y)).getOrElse(0) // 4
你也可以使用for-comprehensions,当你有很长的链代码时,这对于使用干净的代码非常好:
(for(x <- f(1); y <- f(x); z <- f(y)) yield z).getOrElse(0)
答案 1 :(得分:2)
解决此问题的另一种方法是从各种辅助函数返回Either[Command,String]
,而不是Option
。这将允许您使用for
理解,如下所示:
val result = for {
i <- getImage().right
c <- getConf().right
r <- getRide().right
z <- check(r).right
} yield z
// extract either left or right, whichever is occupied
sender ! result.fold(identity, _ => success())
这具有所需的属性,我们会在遇到错误时立即停止,并捕获该特定错误 - 或者继续成功结束。
答案 2 :(得分:1)
我认为您应该能够将大部分内容合并到Option.fold()
中,大致如下:
case MyMessage =>
sender !
getImage().fold(fail("Missing image")) { im =>
getConf().fold(fail("Missing number")) { conf => // conf isn't used
getRide().fold(fail("Ride empty")) { r =>
if (booleanCondition) succeed(true)
else fail("Problem updating")
}
}
}
在这种情况下,这比flatMap
和orElse
简洁得多(见下文)
Option.fold(ifEmpty){f}
如果选项为空则返回ifEmpty
(懒惰地评估),或者如果选项已满,则返回函数f
。
上面的代码假定您创建了帮助函数以获取各种选项(或者您可以内联相关代码)。它还假设您将命令的创建提取到一个或两个辅助函数中,以避免对command
的所有重复引用。
为了进行比较,使用flatMap
的解决方案类似于:
case MyMessage =>
sender !
getImage().flatMap { im =>
getConf().flatMap { conf =>
getRide().flatMap { r =>
if (booleanCondition) Some(succeed(true))
else Some(fail("Problem updating"))
}.orElse(Some(fail("Ride Empty")))
}.orElse(Some(fail("Missing number")))
}.getOrElse(fail("Missing image"))
您可以通过让辅助方法(fail
和succeed
)的变体返回Some[Command]
而不是Command