处理Scala选项[T]

时间:2011-12-16 17:39:33

标签: scala scala-option

我有一个Scala Option[T]。如果值为Some(x),我想使用不返回值(Unit)的进程处理它,但如果它是None,我想打印错误。

我可以使用以下代码执行此操作,但我了解更惯用的方法是将Option[T]视为序列并使用mapforeach等。我这样做吗?

opt match {
  case Some(x) => // process x with no return value, e.g. write x to a file
  case None => // print error message
}

5 个答案:

答案 0 :(得分:6)

我认为显式模式匹配最适合您的用例。

答案 1 :(得分:3)

如果opt.getNoSuchElementException,我建议您简单安全地使用opt本身会引发None例外情况。或者如果你想抛出自己的异常,你可以这样做:

val x = opt.getOrElse(throw new Exception("Your error message"))
// x is of type T

答案 2 :(得分:3)

可悲的是,Scala的Option错过了一种方法来完成这项工作。我加一个:

class OptionWrapper[A](o: Option[A]) {
  def fold[Z](default: => Z)(action: A => Z) = o.map(action).getOrElse(default)
}
implicit def option_has_utility[A](o: Option[A]) = new OptionWrapper(o)

有更好的(在我看来)使用

op.fold{ println("Empty!") }{ x => doStuffWith(x) }

您可以从定义的方式看出可以使用map / getOrElse代替模式匹配。

或者,Either已经有fold方法。所以你可以

op.toRight(()).fold{ _ => println("Empty!") }{ x => doStuffWith(x) }

但是这有点笨拙,因为你必须提供左值(这里是(),即Unit)然后定义一个函数,而不仅仅是说明你想要在{{1 }}

模式匹配也不错,特别是对于更长的代码块。对于简短的,比赛的开销开始妨碍这一点。例如:

None

的语法开销要比

少得多
op.fold{ printError }{ saveUserInput }

因此,一旦你期望它,就会容易理解。

答案 3 :(得分:2)

模式匹配是这里的最佳选择。

但是,如果您想将Option视为一个序列并将其映射到它上面,那么您可以这样做,因为Unit是一个值:

opt map { v =>
  println(v) // process v (result type is Unit)
} getOrElse {
  println("error")
}

顺便说一下,打印错误是某种“反模式”,所以最好抛出异常:

opt.getOrElse(throw new SomeException)

答案 4 :(得分:2)

正如@missingfaktor所说,你处于模式匹配提供最可读结果的确切场景中。 如果Option有一个你想要做某事的值,如果不是你想要做其他事情。

虽然有多种方法可以在Option类型上使用map和其他功能结构,但它们在以下情况下通常很有用:

你想要使用Some case并忽略None case,例如在你的情况下

opt.map(writeToFile(_)) //(...if None just do nothing)

或者您希望将操作链接到多个选项上,并仅在所有选项都是Some时才给出结果。例如,一种方法是:

val concatThreeOptions = 
for {
  n1 <- opt1
  n2 <- opt2
  n3 <- opt3
} yield n1 + n2 + n3 // this will be None if any of the three is None
                     // we will either write them all to a file or none of them

但这些似乎都不是你的情况