当我使用选项编码时,我发现折叠方法非常有用。而不是写我可以做的定义语句
opt.fold(<not_defined>){ defined => }
这很好。但如果我们正在使用多种选择该怎么办。或多个eithers。现在我不得不求助于编写像
这样的代码if (x.isDefined && y.isRight) {
val z = getSomething(x.get)
if (z.isDefined) {
....
根据涉及的内容数量,此代码变得非常嵌套。
是否有一个功能性的技巧,使这个代码有点不嵌套和简洁....就像上面的折叠操作?
答案 0 :(得分:1)
import scala.util._
val opt1 = Some("opt1")
val either2: Either[Error, String] = Right("either2")
val try3: Try[String] = Success("try3")
for {
v1 <- opt1
v2 <- either2.right.toOption
v3 <- try3.toOption
} yield {
println(s"$v1 $v2 $v3")
}
请注意,Either
没有正确的偏见,因此您需要在for comprehension上调用.right
方法(我认为cat或scalaz具有正确的偏差Either)。此外,我们正在将Either
和Try
转换为选项,放弃错误
答案 1 :(得分:1)
.isDefined
跟随.get
调用的情况可以使用自定义提取器进行重构以进行模式匹配:
def getSomething(s: String): Option[String] = if (s.isEmpty) None else Some(s.toUpperCase)
object MyExtractor {
def unapply(t: (Option[String], Either[Int, String])): Option[String] =
t match {
case (Some(x), Right(y)) => getSomething(x)
case _ => None
}
}
val x: Option[String] = Some("hello world")
val y: Either[Int, String] = Right("ok")
(x, y) match {
case MyExtractor(z) => z // let's do something with z
case _ => "world"
}
// HELLO WORLD
我们设法通过显式模式匹配替换所有.isDefined
,.get
甚至.right
调用,这要归功于我们的自定义提取器MyExtractor
。