2016-12-30 27 views
0

關於如何處理期貨列表,StackOverflow有一些建議,但我想嘗試自己的方法。但我無法編譯下面的代碼無法編譯未來列表的代碼

我有期貨的列表。 我想統計他們有多少人通過或失敗。我應該得到(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) 
} 

回答

1

如果你看一下docsrecover的簽名是:

def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Future[U] 

要調用recoverl這是一個Future[Int]所以recover期待一個U >: Int

但是您再次致電go,其返回類型爲Future[(pass, fail)]而非>: Int

2

@ evan058對恢復的簽名是正確的。但是,您可以通過將恢復爲恢復爲來修復程序。

recoverWith恢復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[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) 
} 
+0

難道OP仍然有'(及格,不及格)',而不是一些'U'其中'U>:Int'? –

+0

啊,我明白你的意思了。看起來你需要一個'asInstanceOf [Future [(pass,fail)]]'否則它會抱怨獲得'Future [Any]',但是之後它會爲我運行。 –

+0

男士 - 謝謝。你的意思是這樣嗎?代碼編譯但我得到一個運行時錯誤java.lang.ClassCastException:java.lang.Integer不能轉換爲scala.Tuple2'我現在寫的代碼是'flatMap(x => go(ls ,(t._1 + 1,t._2))) l.asInstanceOf [Future [(pass,fail)]]。recoverWith({case e => go(ls,(t._1 + 1,t._2 ))})' –