我有一个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
}
答案 0 :(得分:6)
我认为显式模式匹配最适合您的用例。
答案 1 :(得分:3)
如果opt.get
为NoSuchElementException
,我建议您简单安全地使用opt
本身会引发None
例外情况。或者如果你想抛出自己的异常,你可以这样做:
val x = opt.getOrElse(throw new Exception("Your error message"))
// x is of type T
答案 2 :(得分:3)
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
但这些似乎都不是你的情况