我有许多函数返回一个 future,它是 for 理解的结果,但我需要在退出时从一些可能的失败中恢复。标准语法似乎将 for 理解捕获为中间结果,如下所示:
def fooBar(): Future[String] = {
val x = for {
x <- foo()
y <- bar(x)
} yield y
x.recover {
case SomeException() => "bah"
}
}
我发现的最好的替代方法是将整个内容括在括号中以便理解:
def fooBar(): Future[String] = (for {
x <- foo()
y <- bar(x)
} yield y).recover {
case SomeException() => "bah"
}
这看起来更像是一种捷径,而不是语法的改进,所以我想知道是否有更好的方法将恢复编织到理解中?
最佳答案
一些大括号调整会有所帮助,尽管有些人更喜欢在多行表达式中使用大括号而不是括号:
scala> def f = (
| for {
| x <- foo;
| y <- bar(x)
| } yield y
| ) recover {
| case _: NullPointerException => -1
| }
f: scala.concurrent.Future[Int]
如果你不喜欢
scala> foo flatMap bar recover { case _: NullPointerException => -1 }
res9: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@3efe7086
你可以使用所有语法:
object Test extends App {
import concurrent._
import duration.Duration._
import ExecutionContext.Implicits._
type ~>[A, B] = PartialFunction[A, B]
type NPE = NullPointerException
class `recovering future`[A, R >: A](val f: Future[A], val pf: Throwable ~> R) {
def map[B >: A <: R](m: A => B) = new `recovering future`[B, R](f map m, pf)
def flatMap[B >: A <: R](m: A => Future[B]) = new `recovering future`[B, R](f flatMap m, pf)
def recovered: Future[R] = f recover pf
}
object `recovering future` {
implicit def `back to the future`[A, R >: A](x: `recovering future`[A, R]): Future[R] = x.recovered
}
implicit class `inline recoverer`[A](val f: Future[A]) {
def recovering[B >: A](pf: Throwable ~> B) = new `recovering future`(f, pf)
}
def f = Future(8)
def g(i: Int) = Future(42 + i)
def e(i: Int): Future[Int] = Future((null: String).length)
朴素:
for {
x <- f
y <- g(x)
} Console println y // 50
并且内联恢复:
def compute: Future[Int] =
for {
x <- f recovering { case _: NPE => -1 }
y <- g(x)
} yield y
Console println (Await result (compute, Inf)) // 50
或者显示失败的案例:
def fail: Future[Int] =
for {
x <- f recovering { case _: NPE => -1 }
y <- e(x)
} yield y
Console println (Await result (fail, Inf)) // -1
}
如果你那样挥杆。
关于scala - 用于从 for 理解中恢复的更好语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25732570/