给定一个选项,获取其值或尝试抛出异常的惯用方法是什么?
def foo() : String = {
val x : Option[String] = ...
x.getOrException()
}
给定一个选项,获取其值或尝试抛出异常的惯用方法是什么?
def foo() : String = {
val x : Option[String] = ...
x.getOrException()
}
“throw
语句”实际上是 Scala 中的表达式,它具有 type Nothing
,它是所有其他类型的子类型。这意味着您可以只使用普通的 old getOrElse
:
def myGet[A](oa: Option[A]) = oa.getOrElse(throw new RuntimeException("Can't."))
不过,你真的,真的不应该这样做。
(编辑:这不是最好或最惯用的方法。我在不熟悉 Scala 时写了它。我把它留在这里作为如何不这样做的例子。现在我会像 @TravisBrown 那样做)
我认为这实际上归结为两件事:
如果在你的代码中你期望值在那里,并且在远程情况下你不希望你的程序快速失败,那么我只会做一个正常的get
,让 Scala 抛出一个NoSuchElementException
如果没有价值:
def foo() : 字符串 = { val x : 选项 [字符串] = ... x.get }
如果您想以不同的方式处理此案(抛出您自己的异常),我认为更优雅的方式如下所示:
def foo(): 字符串 = { val x: 选项 [字符串] = 无 x匹配{ 案例一些(价值)=>价值 case None => throw new MyRuntimeException("blah") } }
Option
当然,如果您想为None
您将使用的情况提供自己的替代值getOrElse
:
def foo(): 字符串 = { val x: 选项 [字符串] = 无 x.getOrElse("我的替代值") }
只需使用 .get 方法。
def get[T](o:Option[T]) = o.get
如果 o 是 None 的实例,它将抛出 NoSuchElementException。
基本上,我会使用这样的选项:
def addPrint(oi:Option[Int]) = oi.map(_+1).foreach(println)
addPrint(Some(41))
addPrint(Some(1336))
addPrint(None)
以避免您的具体问题。
我希望这将帮助您了解如何使用类型来表示错误(以及通常的影响)。
用于Option
返回可选值。例如- 无法在存储中找到实体。
用于Option(possiblyNull)
避免Some(null)
.
用于Either[Error, T]
报告预期的失败。 例如- 电子邮件格式错误,无法将字符串解析为数字等。
将您的错误建模为ADT(简单地说是类型层次结构)以使用它,例如,在 Either 的左侧来表示更复杂的错误场景。
throwException
仅用于表示意外且不可恢复的故障。就像缺少配置文件一样。
使用Either.catchOnly
or Try
or Cats.IO
(高级)而不是 catch 块来处理意外故障。提示:您仍然可以使用 ADT,但可以从 throwables扩展它们。更多关于Either
vsTry
。
使用Validated
Cats lib 中的数据类型而不是快速失败 ( Either
) 来累积错误,但更喜欢模块级别的 Either 以简化程序的组合(以具有相同的类型)。例如——表单数据验证、解析错误累积。
使用提到的类型并且不要抢先优化程序- 因为很可能瓶颈出现在业务逻辑中,而不是在效果类型中。
这种方法将简化代码的维护和更新,因为您无需了解实现细节(也称为本地推理)即可对其进行推理。此外 - 减少错误 - 您不能错过类型中的错误。并且更容易编写程序(在map
,flatMap
和其他组合器的帮助下) - 因为它在类型级别上更简单,而不是非本地异常和副作用。
更多关于学习函数式 Scala 的信息。
但请注意,有时使用这种方法,类型可能会堆积起来,并且可能会变得更难组合。例如,给定:x: Future[Either[Error, Option[T]]]
你可以做什么:
map
和flatMap
结合模式匹配来组成这些类型的不同值,例如:x.faltMap { case Right(Some(v)) => anotherFuture(v); case Left(er) => ... }
Future[Option[T]]
最后,在您的情况下,一种选择是:
def foo() : Either[Error, String] = {
val x : Option[String] = ...
x match {
case Some(v) => Right(v)
case None => Left(Error(reason))
}
}
Scala 现在支持使用getOrElse()
方法在地图上进行此操作,请参阅此处的文档
正如已经指出的,在 Scala 中抛出异常也是一个表达式。
因此,您可以执行以下操作:
myMap.getOrElse(myKey, throw new MyCustomException("Custom Message HERE")