簡體   English   中英

獲取選項值或拋出異常

[英]Get Option value or throw an exception

給定一個選項,獲取其值或嘗試拋出異常的慣用方法是什么?

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

throw “語句”實際上是 Scala 中的一個表達式,它的類型為Nothing ,它是所有其他類型的子類型。 這意味着您可以只使用普通的舊getOrElse

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

不過,你真的,真的不應該這樣做。

(編輯:這不是最好或最慣用的方法。我在不熟悉 Scala 的時候寫的。我把它留在這里作為如何這樣做的例子。現在我會像@TravisBrown 那樣做)

我認為它實際上歸結為兩件事:

  • 你有多確定值在那里?
  • 如果不是,你想如何反應

如果在您的代碼中的那個時候您希望該值存在,並且在遠程情況下您不希望您的程序快速失敗,那么我只會做一個正常的get並讓 Scala 拋出一個NoSuchElementException如果有沒有價值:

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

如果您想以不同的方式處理案例(拋出您自己的異常),我認為更優雅的方式如下所示:

def foo(): String = {
  val x: Option[String] = None
  x match {
    case Some(value) => value
    case None => throw new MyRuntimeException("blah")
  }
}

當然,如果您想為OptionNone的情況提供您自己的替代值,您只需使用getOrElse

def foo(): String = {
  val x: Option[String] = None
  x.getOrElse("my alternative value")
}

只需使用 .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)

避免你的具體問題。

我希望這將幫助您了解如何使用類型表示錯誤(以及一般的影響)。

函數式 Scala 中的錯誤處理策略

  • 使用Option返回可選值。 例如- 無法在存儲中找到實​​體。

  • 使用Option(possiblyNull)來避免Some(null)實例。

  • 使用Either[Error, T]報告預期的失敗。 例如- 電子郵件格式錯誤,無法將字符串解析為數字等。

  • 將您的錯誤建模為ADT (簡單地說是一種類型層次結構)以使用它,例如,在或者的左側表示更復雜的錯誤場景。

  • 拋出Exception僅用於發出意外和不可恢復的故障信號。 就像缺少配置文件一樣。

  • 使用Either.catchOnlyTryCats.IO (高級)而不是catch 塊來處理意外故障。 提示:您仍然可以使用 ADT,但可以從 throwable 擴展它們 更多關於“ Either與“ Try

  • 使用 Cats lib 中的Validated data-type 來累積錯誤而不是快速失敗( Either ),但更喜歡在模塊級別使用Either 來簡化程序的組合(具有相同的類型)。 例如——表單數據驗證、解析錯誤累積。

  • 使用提到的類型並且不要搶先優化程序- 因為最有可能的瓶頸是業務邏輯,而不是效果類型。

這種方法將簡化代碼的維護和更新,因為您可以在不涉及實現細節(又名本地推理)的情況下對其進行推理。 此外 - 減少錯誤 - 您不能錯過類型中的錯誤。 並且更容易flatMap程序(在mapflatMap和其他組合器的幫助下) - 因為它在類型級別更簡單,而不是非本地異常和副作用。
更多關於學習函數式 Scala 的信息。


但請注意,有時使用這種方法類型可能會堆積在一起,並且可能會變得更難組合。 給定,例如: x: Future[Either[Error, Option[T]]]你可以做什么:

  • 使用mapflatMap結合模式匹配來組合此類類型的不同值,例如:
x.faltMap { case Right(Some(v)) => anotherFuture(v); case Left(er) => ... }
  • 如果它沒有幫助,您可以嘗試使用MonadTransformers (不要害怕名稱,它只是圍繞效果類型(例如Either 和 Future)的包裝器)
  • 此外,一個選項是通過從 Throwable 擴展它們以將其與 Future 統一來簡化您的錯誤 ADT,然后它將是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")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM