scala 获取选项值或抛出异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16263560/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 05:14:42  来源:igfitidea点击:

Get Option value or throw an exception

scala

提问by ripper234

Given an Option, what is the idiomatic way to get its value or throw an exception trying?

给定一个选项,获取其值或尝试抛出异常的惯用方法是什么?

def foo() : String = {
  val x : Option[String] = ...
  x.getOrException()
}

采纳答案by Sebastian N.

(EDIT: this is not the best or most idiomatic way to do it. I wrote it when I was not familiar with Scala. I leave it here for an example of how notto do it. Nowadays I would do as @TravisBrown)

(编辑:这不是最好或最惯用的方法。我在不熟悉 Scala 的时候写的。我把它留在这里作为如何这样做的例子。现在我会像@TravisBrown 那样做)

I think it really boils down to two things:

我认为它实际上归结为两件事:

  • how sureare you that the value is there?
  • how do you want to reactif it isn't?
  • 你有多确定值在那里?
  • 如果不是,你想如何反应

If at that point in your code you expectthe value to be there, and in the remote case that it isn't you want your program to failfast, then I would only do a normal getand let Scala throw a NoSuchElementExceptionif there was no value:

如果在您的代码中的那个时候,您希望该值存在,并且在远程情况下您不希望您的程序快速失败,那么我只会做一个正常的getNoSuchElementException如果没有值,让 Scala 抛出一个:

def foo() : String = {
  val x : 选项[字符串] = ...
  x.get
}

If you want to handle the case differently (throw your own exception) I think a more elegant way would look like this:

如果您想以不同的方式处理案例(抛出您自己的异常),我认为更优雅的方式如下所示:

def foo(): 字符串 = {
  val x: 选项[字符串] = 无
  x 匹配 {
    case Some(value) => value
    case None => throw new MyRuntimeException("blah")
  }
} 

And of course if you want to supply your own alternative value for the case that the Optionis Noneyou would just use getOrElse:

当然,如果您想OptionNone您将使用的情况提供您自己的替代值getOrElse

def foo(): 字符串 = {
  val x: 选项[字符串] = 无
  x.getOrElse("我的替代值")
} 

回答by Travis Brown

A throw"statement" is really an expression in Scala, and it has type Nothing, which is a subtype of every other type. This means you can just use plain old getOrElse:

一个throw“说法”确实是在Scala中的表达,它有型Nothing,这是每一个其他类型的子类型。这意味着您可以只使用普通的 old getOrElse

def myGet[A](oa: Option[A]) = oa.getOrElse(throw new RuntimeException("Can't."))

You really, really shouldn't be doing this, though.

不过,你真的,真的不应该这样做。

回答by Felix

Just use the .get method.

只需使用 .get 方法。

def get[T](o:Option[T]) = o.get

It will throw a NoSuchElementException if o is an instance of None.

如果 o 是 None 的实例,它将抛出 NoSuchElementException。

Basically, I would work with options like this:

基本上,我会使用这样的选项:

def addPrint(oi:Option[Int]) = oi.map(_+1).foreach(println)
addPrint(Some(41))
addPrint(Some(1336))
addPrint(None)

to avoid your specific question.

避免你的具体问题。

回答by Albert Bikeev

I hope this will help you to understand how to represent errors (and generally effects) using types.

我希望这将帮助您了解如何使用类型表示错误(以及一般的影响)。

Error handling strategies in functional Scala

函数式 Scala 中的错误处理策略

  • Use Optionto return optional values. For example- fail to find entity in storage.
  • Use Option(possiblyNull)to avoid instances of Some(null).

  • Use Either[Error, T]to report expected failure.For example- email format is wrong, cannot parse a string to a number, etc.

  • Model your errors as ADTs(simply speaking kind of type hierarchies) to use it, for example, on the Left of the Either to represent more complex error scenarios.

  • Throw Exceptiononly to signal unexpected and not-recoverable failures.Like missing config file.

  • Use Either.catchOnlyor Tryor Cats.IO(advanced) rather than a catch block for handling unexpected failures. Hint: You can still use ADT but extend themfrom throwables. More about Eithervs Try.

  • Use Validateddata-type from Cats lib to accumulate errors rather than fail-fast (Either), but prefer Either's on module-level to simplify the composition of the program (to have the same types). For example- form data validation, parsing errors accumulation.

  • Use mentioned types and don't optimize program preemptively- since most probably, bottle-necks would be in business logic, not in effect types.

  • 使用Option返回可选值。例如- 无法在存储中找到实​​体。
  • 使用Option(possiblyNull)到的避免实例Some(null)

  • 使用Either[Error, T]报告预期故障。例如- 电子邮件格式错误,无法将字符串解析为数字等。

  • 将您的错误建模为ADT(简单地说是一种类型层次结构)以使用它,例如,在或者的左侧表示更复杂的错误场景。

  • 抛出Exception仅用于发出意外且不可恢复的故障的信号。就像缺少配置文件一样。

  • 使用Either.catchOnlyorTryCats.IO(高级)而不是 catch 块来处理意外故障。提示:您仍然可以使用 ADT,但可以从 throwable扩展它们。更多关于EithervsTry

  • 使用ValidatedCats 库中的数据类型来累积错误而不是快速失败 ( Either),但更喜欢在模块级别上使用Either 来简化程序的组成(具有相同的类型)。例如——表单数据验证、解析错误累积。

  • 使用提到的类型并且不要抢先优化程序- 因为最有可能的瓶颈是业务逻辑,而不是效果类型。

Such an approach will simplify maintenance and updates of your code since you can reason about it without going to implementation specifics (aka local-reasoning). Also - reduce bugs - you cannot miss an error in the type. And compose the program easier (with help of map, flatMapand other combinators) - since it's simpler on type level, rather than with non-local exceptions and side-effects.
Moreabout learning functional Scala.

这种方法将简化代码的维护和更新,因为您可以在不涉及实现细节(又名本地推理)的情况下对其进行推理。此外 - 减少错误 - 您不能错过类型中的错误。并且更容易地编写程序(在map,flatMap和其他组合器的帮助下) - 因为它在类型级别上更简单,而不是非本地异常和副作用。
更多关于学习函数式 Scala 的信息。



But be aware that sometimes with this approach types could stack up and it could become harder to compose things. Given, for example: x: Future[Either[Error, Option[T]]]What you can do:

但请注意,有时使用这种方法类型可能会堆积起来,并且可能会变得更难组合。给定,例如:x: Future[Either[Error, Option[T]]]你可以做什么:

  • Use mapand flatMapin combination with pattern-matching to compose different values of such types, for example:
  • 使用mapflatMap结合模式匹配来组合此类类型的不同值,例如:
x.faltMap { case Right(Some(v)) => anotherFuture(v); case Left(er) => ... }
  • If it doesn't help you can try to use MonadTransformers(don't be scared of the name, it's just wrappers around the effect types like Either and Future)
  • Also, an option is to simplify your errors ADT by extending themfrom the Throwable to unify it with Future, then it'll be Future[Option[T]]
  • 如果它没有帮助,您可以尝试使用MonadTransformers(不要害怕名称,它只是对效果类型的包装,例如Either 和Future)
  • 此外,一个选项是通过从 Throwable扩展它们以将其与 Future 统一来简化您的错误 ADT ,然后它将是Future[Option[T]]





And finally, in your case one option will be:

最后,在您的情况下,一种选择是:

def foo() : Either[Error, String] = {
    val x : Option[String] = ...
    x match {
        case Some(v) => Right(v)
        case None => Left(Error(reason))
    }
}

回答by Moha the almighty camel

Scala now support this operation on maps using getOrElse()method, see documentation here

Scala 现在支持使用getOrElse()方法对地图进行此操作,请参阅此处的文档

As pointed out already, throwing an exception in Scala is an expression as well.

正如已经指出的,在 Scala 中抛出异常也是一个表达式。

So you can do the following:

因此,您可以执行以下操作:

myMap.getOrElse(myKey, throw new MyCustomException("Custom Message HERE")