我有一个
val file: Option = xxxx
val request: Option = yyyyy
这些是相互排斥的,所以理解是我想要的。
有一种干净的方式吗?我想也许在元组上匹配可能是最干净的但是想知道是否有一些map或flatMap recoverWith / rescue trickery看起来可读且简单。
答案 0 :(得分:2)
您可以使用模式匹配,但它不能很好地扩展以添加更多选项。
(file, request) match {
case (Some(f), None) => // handle file
case (None, Some(r)) => // handle request
case (None, None) => // error case
case (Some(_), Some(_)) => // error case
}
但是,如果你真的可以做到#34;所有无"唯一的错误情况,而不是错误的多个Some,你可以很容易地把它们放在你的首选顺序,只有最重要的一个不是没有 -
// file is more important, ignore request unless file is None
Seq(file, request).flatten.headOption match {
case Some(x) => // x is either file or request's value
case None => // All None, error
}
答案 1 :(得分:1)
嗯,就是这样:
val result = List(file, request).flatten
if (result.length != 1) throw(...) else [do something with result.head]
或稍微清洁:
List(file, request).flatten match { case x::Nil => x ; case _ => throw (...)}
但两种表达意图的方式都不明确,所以我不确定是否也会推荐。
答案 2 :(得分:1)
这不够简单易读:
(x filter (_ => y.isEmpty)) orElse (y filter (_ => x.isEmpty)) orElse ???
答案 3 :(得分:1)
正如其他回应所示,我认为没有一种简单的方法。在这种情况下,我喜欢创建一个新的解构函数(unapply)。它将使意图清晰,并保持您的代码整洁。
object Xor {
def unapply[T](p: (Option[T], Option[T])): Option[T] = p match {
case (None, b @ Some(_)) => b
case (a @ Some(_), None) => a
case _ => None
}
}
val file: Option[Int] = ???
val request: Option[Int] = ???
(file, request) match {
case Xor(x) => // use x
case _ => // error
}
答案 4 :(得分:0)
我建议将文件和请求的2个val转换为Either构造。要做到这一点,我首选的方法是使用其他用户已在此处建议的模式匹配。
当您的代码收到Either而不是2个参数时,您将确定只有其中一个参数存在,这样您就可以编写功能更强大的代码了。
获得Either后,可以使用.fold(handleFileFunc,handleReqFunc)方法。
def handleFileFunc(f: File) = ???
def handleReqFunc(r: Request) = ???
val data: Either[File, Request] = ???
data fold (handleFileFunc, handleReqFunc)