scala选项互斥值

时间:2014-12-11 19:48:09

标签: scala

我有一个

val file: Option = xxxx
val request: Option = yyyyy

这些是相互排斥的,所以理解是我想要的。

有一种干净的方式吗?
  1. 如果两者都为无
  2. 则抛出验证异常
  3. 如果两者都是Some(x)
  4. 则抛出验证异常
  5. 处理一个或另一个
  6. 我想也许在元组上匹配可能是最干净的但是想知道是否有一些map或flatMap recoverWith / rescue trickery看起来可读且简单。

5 个答案:

答案 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)
相关问题