val one: Option[Int] = None
val two = Some(2)
Option(one.getOrElse(two.getOrElse(null))) // Gives me Some(2) which I want
val one = Some(1)
val two = None
Option(one.getOrElse(two.getOrElse(null))) // Gives me Some(1) which I want
val one: Option[Int] = None
val two: Option[Int] = None
Option(one.getOrElse(two.getOrElse(null))) // Gives me None which I want
val one = Some(1)
val two = Some(2)
Option(one.getOrElse(two.getOrElse(null))) // Gives me Some(1) when I want an exception
我简要地研究了Either类型,但它似乎是“表示两种可能类型之一的值”。我错过了一些数据结构还是Monad?基本上我想要一个明确的(并且如果两者都有价值则抛出错误)如果可用则获得一个或获得无
答案 0 :(得分:9)
我不知道任何预先建造的东西,所以这是一个功能:
def xor[T](x: Option[T], y: Option[T]): Option[T] = (x, y) match {
case (Some(_), None) => x
case (None, Some(_)) => y
case (None, None) => None
case _ => throw new Exception()
}
答案 1 :(得分:4)
def xor[T](a: Option[T], b: Option[T]) =
a orElse b ensuring (_ => a zip b isEmpty)
答案 2 :(得分:3)
如果是简单的情况,我可能会去老学校。
scala> implicit class optxor[A](val opt: Option[A]) extends AnyVal {
| def xor(other: Option[A]) = if (opt.isEmpty) other else if (other.isEmpty) opt else ??? }
defined class optxor
scala> one xor two
res18: Option[Int] = Some(2)
scala> two xor three
scala.NotImplementedError: an implementation is missing
at scala.Predef$.$qmark$qmark$qmark(Predef.scala:225)
at optxor$.xor$extension(<console>:8)
... 33 elided
答案 3 :(得分:2)
这是我的功能版本
val options = Seq(one, two).flatten
if (options.size > 1) throw new Exception("two options were provided")
options.headOption
答案 4 :(得分:1)
我会使用像gzou回答的模式匹配函数来解决这个问题,但这里只是一个内容:
one.map{x => two.foreach(y => throw new Exception("both defined")); x}.orElse(two)
答案 5 :(得分:0)
或者,
scala> val one: Option[Int] = None
one: Option[Int] = None
scala> val two = Option(2)
two: Option[Int] = Some(2)
scala> val three = Option(3)
three: Option[Int] = Some(3)
scala> (for (_ <- one; _ <- two) yield ???) orElse one orElse two
res0: Option[Int] = Some(2)
scala> (for (_ <- three; _ <- two) yield ???) orElse three orElse two
scala.NotImplementedError: an implementation is missing
at scala.Predef$.$qmark$qmark$qmark(Predef.scala:225)
at $anonfun$1$$anonfun$apply$1.apply(<console>:10)
at $anonfun$1$$anonfun$apply$1.apply(<console>:10)
at scala.Option.map(Option.scala:145)
at $anonfun$1.apply(<console>:10)
at $anonfun$1.apply(<console>:10)
at scala.Option.flatMap(Option.scala:170)
... 33 elided
desugaring to
scala> one flatMap (_ => two) map (_ => ???) orElse one orElse two
res3: Option[Int] = Some(2)
但在惯用的情况下,很难想象要做其中任何一种。
答案 6 :(得分:0)
这个怎么样?
import scala.util.Try
object XorOption {
def xorOptions[T](one: Option[T], two: Option[T]): Try[Option[T]] = {
Try {
for (x <- one; y <- two) throw new RuntimeException
one.orElse(two)
}
}
def main(args: Array[String]) {
val testData = List(
(None, None),
(None, Some(2)),
(Some(1), None),
(Some(1), Some(2)))
for (t <- testData) {
println(t + " => " + xorOptions(t._1, t._2))
}
}
}
输出:
(None,None) => Success(None)
(None,Some(2)) => Success(Some(2))
(Some(1),None) => Success(Some(1))
(Some(1),Some(2)) => Failure(java.lang.RuntimeException)
答案 7 :(得分:0)
List(Some(1), Some(2)).flatten match {
case x :: Nil => Some(x)
case Nil => None
case _ => throw new Exception
}
答案 8 :(得分:0)
我们可以将2个Option
与Iterable
的{{3}}运算符组合为Option
,从而对可迭代对象(而不是选项元组)进行模式匹配:
optionA ++ optionB match {
case Seq(x, y) => throw new Exception
case x => x.headOption
}
// None and None => None
// Some(5) and None => Some(5)
// None and Some(5) => Some(5)
// Some(5) and Some(3) => Exception
注意headOption
可以很好地处理具有1个元素的列表和空列表。