给定一个Option,获得其价值或引发异常尝试的惯用方式是什么?
def foo() : String = {
val x : Option[String] = ...
x.getOrException()
}
给定一个Option,获得其价值或引发异常尝试的惯用方式是什么?
def foo() : String = {
val x : Option[String] = ...
x.getOrException()
}
NoSuchElementException
的异常。同样,在大多数情况下,此方法可能会安全地返回None。
Answers:
(编辑:这不是最好的或最惯用的方式。我在不熟悉Scala的时候写了它。我在这里留了一个不怎么做的示例。如今,我将作为@TravisBrown来做。)
我认为这可以归结为两点:
如果那时您希望代码中存在该值,而在远程情况下您不希望您的程序快速失败,那么我只会做一个普通的操作get
,NoSuchElementException
如果没有值,则让Scala抛出a :
def foo():字符串= { val x:Option [String] = ... x.get }
如果您想以不同的方式处理案件(引发您自己的异常),我认为一种更优雅的方式如下所示:
def foo():字符串= { val x:Option [String] =无 x匹配{ 情况Some(value)=> value 情况None =>抛出新的MyRuntimeException(“ blah”) } }
当然,如果你想为的情况下提供自己的替代值Option
是None
你只需使用getOrElse
:
def foo():字符串= { val x:Option [String] =无 x.getOrElse(“我的替代值”) }
getOrElse
如果这是所有人想要做的,那应该是首选。我只想举例说明“如果已定义,则求值为X,否则,则抛出异常”的情况。
getOrElse
:x.getOrElse(throw new MyRuntimeException("message"))
一个throw
“说法”确实是在Scala中的表达,它有型Nothing
,这是每一个其他类型的子类型。这意味着您可以只使用普通的old getOrElse
:
def myGet[A](oa: Option[A]) = oa.getOrElse(throw new RuntimeException("Can't."))
不过,您确实不应该这样做。
OutOfMemoryError
)保存异常)。
只需使用.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)
避免您的特定问题。
get
这也不是个好主意-它只是说明您所做的事情令人不快。getOrElse
当您确定这不仅是一次性代码并希望使其更安全时,更难以错过使用并明确引发异常的情况。
我希望这将帮助您了解如何使用类型来表示错误(通常是效果)。
使用Option
返回可选值。例如-无法在存储中找到实体。
使用Option(possiblyNull)
到的避免实例Some(null)
。
使用Either[Error, T]
报告预期故障。 例如-电子邮件格式错误,无法将字符串解析为数字等。
将您的错误建模为ADT(简而言之类型类型层次结构)以使用它,例如,在“任意一个”的左侧,以表示更复杂的错误情况。
抛出Exception
仅表示意外和不可恢复的故障。就像缺少配置文件。
使用Either.catchOnly
orTry
或Cats.IO
(高级)而不是catch块来处理意外的故障。提示:您仍然可以使用ADT,但可以将它们从throwables扩展。关于Either
vs的Try
更多信息。
使用Validated
Cats lib中的数据类型来累积错误,而不是使用fail-fast(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))
}
}
.get
呢?