0

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

我可以使用以下代码来执行此操作,但我知道更惯用的方法是将Option[T]视为序列并使用map,foreach等。我该怎么做?

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

5 回答 5

6

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

于 2011-12-16T18:02:09.213 回答
3

我建议简单安全地使用opt.getwhich 本身会引发NoSuchElementException异常 if optis None。或者如果你想抛出自己的异常,你可以这样做:

val x = opt.getOrElse(throw new Exception("Your error message"))
// x is of type T
于 2011-12-16T17:44:40.743 回答
3

遗憾的是,ScalaOption缺少一种方法来做到这一点。我加一个:

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),然后在其上定义一个函数,而不仅仅是说明您想要在 上发生什么None

模式匹配也不错,尤其是对于较长的代码块。对于简短的比赛,比赛的开销开始妨碍得分。例如:

op.fold{ printError }{ saveUserInput }

语法开销比

op match {
  case Some(x) => saveUserInput(x)
  case None => printError
}

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

于 2011-12-16T18:56:00.383 回答
2

正如@missingfaktor 所说,您正处于模式匹配给出最易读结果的确切场景中。如果 Option 有一个值,你想做某事,如果没有,你想做其他事情。

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

您想使用 Some 案例并忽略 None 案例,例如在您的案例中

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

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

于 2011-12-16T18:27:15.680 回答
2

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

但是,如果您想将 Option 视为一个序列并对其进行映射,则可以这样做,因为 Unit 是一个值:

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

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

opt.getOrElse(throw new SomeException)
于 2011-12-16T18:26:20.950 回答