StackOverflow上有一些关于如何处理Futures列表的建议,但我想尝试自己的方法。但我无法编译以下代码
我有一份期货清单。 我想算一下他们中有多少人通过或失败了。我应该得到(2,1) 我将它存储在一个元组中 我想要采用的方法是遍历列表中的每个元素。列表的元素是Future [Int]。对于每个元素,我调用flatMap调用下一个递归循环(我假设如果调用flatMap,那么特定的未来会成功,所以我增加传递计数)。类似地,我想在恢复和递增失败计数中调用递归的下一个循环,但我收到了编译错误。
import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success, Try}
import scala.concurrent.duration._
import scala.language.postfixOps
object ConcurrencyExample extends App {
type pass = Int
type fail = Int
val time = System.currentTimeMillis()
//use recursion to process each Future in the list
def segregate(l:List[Future[Int]]):Future[Tuple2[pass,fail]] = {
def go(l:List[Future[Int]],t:Tuple2[pass,fail]):Future[Tuple2[pass,fail]] = {
l match {
case Nil => Future{t}
//l is List of Future[Int]. flatMap each successful Future
//recover each failed Future
case l::ls => {
l flatMap (x => go(ls, (t._1 + 1, t._2)))
**l.recover({ case e => go(ls, (t._1 + 1, t._2))})**//I get error here
}
}
}
go(l,(0,0))
}
//hardcoded future
val futures2: List[Future[Int]] = List(Future {
1
}, Future {
2
}, Future {
throw new Exception("error")
})
val result = segregate(futures2)
result onComplete {
case Success(v) => println("pp:" + v)
case Failure(v) => println("fp:" + v)
}
Await.result(result,1000 millis)
}
答案 0 :(得分:2)
@ evan058关于恢复的签名是正确的。但您可以通过将 recover 更改为 recoverWith 来修复您的程序。
recoverWith 是 recover ,因为 flatMap 是 map 。
这是完整的解决方案(具有轻微的风格改进):
import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success, Try}
import scala.concurrent.duration._
import scala.language.postfixOps
object ConcurrencyExample extends App {
type pass = Int
type fail = Int
val time = System.currentTimeMillis()
//use recursion to process each Future in the list
def segregate[T](fs:List[Future[T]]):Future[(pass,fail)] = {
def go(fs:List[Future[T]],r:Future[(pass,fail)]):Future[(pass,fail)] = fs match {
case Nil => r
case l::ls =>
val fx = l.transform({_ => (1, 0)}, identity).recoverWith[(pass,fail)]({case _: Exception => Future(0, 1) })
for (x <- fx; t <- r; g <- go(ls, Future(t._1+x._1,t._2+x._2))) yield g
}
go(fs,Future((0,0)))
}
//hardcoded future
val futures2 = List(Future(1), Future(2), Future(throw new Exception("error")))
val result = segregate(futures2)
result onComplete {
case Success(v) => println(s"successes: ${v._1}, failures: ${v._2}")
case Failure(v) => v.printStackTrace()
}
Await.result(result,1000 millis)
}
答案 1 :(得分:1)
如果您查看docs,则recover
的签名为:
def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Future[U]
您在recover
上呼叫l
这是Future[Int]
,因此recover
期待U >: Int
。
但是,您再次呼叫go
,其返回类型Future[(pass, fail)]
不是>: Int
。