[英]Cleaner way to throw exception if unable to get return value from Try execution
[英]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") } }
當然,如果您想為Option
為None
的情況提供您自己的替代值,您只需使用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)
避免你的具體問題。
我希望這將幫助您了解如何使用類型表示錯誤(以及一般的影響)。
使用Option
返回可選值。 例如- 無法在存儲中找到實體。
使用Option(possiblyNull)
來避免Some(null)
實例。
使用Either[Error, T]
報告預期的失敗。 例如- 電子郵件格式錯誤,無法將字符串解析為數字等。
將您的錯誤建模為ADT (簡單地說是一種類型層次結構)以使用它,例如,在或者的左側表示更復雜的錯誤場景。
拋出Exception
僅用於發出意外和不可恢復的故障信號。 就像缺少配置文件一樣。
使用Either.catchOnly
或Try
或Cats.IO
(高級)而不是catch 塊來處理意外故障。 提示:您仍然可以使用 ADT,但可以從 throwable 擴展它們。 更多關於“ Either
與“ Try
。
使用 Cats lib 中的Validated
data-type 來累積錯誤而不是快速失敗( Either
),但更喜歡在模塊級別使用Either 來簡化程序的組合(具有相同的類型)。 例如——表單數據驗證、解析錯誤累積。
使用提到的類型並且不要搶先優化程序- 因為最有可能的瓶頸是業務邏輯,而不是效果類型。
這種方法將簡化代碼的維護和更新,因為您可以在不涉及實現細節(又名本地推理)的情況下對其進行推理。 此外 - 減少錯誤 - 您不能錯過類型中的錯誤。 並且更容易flatMap
程序(在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")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.