ScalaTry構造與其一起flatMap作業并不能像我期望或希望的那樣作業。TL;DR 是我想做一系列可能以兩種方式失敗的操作:或者通過引發例外,應該在呼叫堆疊中提升并捕獲更高的位置,或者通過回傳Failure,因為失敗在邏輯上必須是在程式的不同部分處理。
我希望這樣的事情可以解決問題:
def firstStepSucceeds(): Try[Int] = Try {
1
}
def secondStepThrows(input: Int) = {
throw new Exception("Exception thrown in second step")
}
// I expect this to propagate the exception thrown in secondStepThrows
firstStepSucceeds() flatMap (secondStepThrows _)
(完整的 Scastie 示例)
但是,在這種情況下,flatMap()呼叫實際上隱式地捕獲了由 拋出的未捕獲例外secondStepThrows,這不是我想要的(這就是我忽略該Try塊的原因)。有沒有辦法在沒有隱式例外捕獲的情況下獲得相同的行為?
uj5u.com熱心網友回復:
a 中發生的事情Try應該留在 a 中Try。如果回傳 a 的函式有時也會拋出例外,大多數 Scala 程式員會感到非常驚訝。Try
如果你想在不同的地方處理例外,典型的模式是通過例外的型別來區分。所以
val partiallyRecoveredTry = originalTry.recover{
case _: SecondStepException => "second step had an exception"
}
// Further up the call stack
partiallyRecoveredTry.getOrElse("first step had an exception")
uj5u.com熱心網友回復:
Try.flatMap() 沒有隱式捕獲例外,這是 Try 的本質。當您使用它時,它非常明確,這就是目標。
我真的不明白你想要什么,但是這樣的事情對你來說可能嗎?
try {
val first = firstStepSucceeds()
val second = first.map(secondStepThrows).get
val third = secondStepFails(second)
// ...
}
catch {
case e: Exception => ???
}
uj5u.com熱心網友回復:
我做了一些進一步的實驗,最終得到的是重新實作Tryas (現在偏右,因此是 monadic)Either:
object CatchAll {
def apply[SomeType](block: => SomeType) = try { Right(block) }
catch { case e: Throwable => Left(e) }
}
def firstStepSucceeds() = CatchAll {
1
}
def firstStepFails() = CatchAll {
throw new Exception("First step failed")
}
def secondStepSucceeds(input: Int) = CatchAll {
input 1
}
def secondStepFails(input: Int) = CatchAll {
throw new Exception("Second step failed in try block!")
}
def secondStepThrows(input: Int) = {
throw new Exception("Second step failed unexpectedly!")
}
firstStepSucceeds() flatMap (secondStepSucceeds _)
firstStepFails() flatMap (secondStepSucceeds _)
firstStepSucceeds() flatMap (secondStepFails _)
// This now throws an exception as expected
//firstStepSucceeds() flatMap (secondStepThrows _)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/463276.html
