2016-07-01 34 views
0

我有一些適用於簡單情況(2期貨)的代碼,但我無法完全找到將其推廣爲無限期數量期貨的方式。斯卡拉有條件期貨的組合

我想要做的是創建一些調用未來的代碼,當未來完成時調用另一個代碼,並在完成時調用另一個代碼,依此類推。

我需要在調用下一個調用之前完成每個調用的結果,因爲我可能不需要再次調用它(這是我的停止條件)。

我知道這可以通過遞歸明確地解決,但是我想,如果可能的話,使用理解和/或摺疊的解決方案。我覺得必須有這樣的解決方案,但我不能正確寫出它。

下面是產生兩個隨機整數

def nextValue: Future[List[Int]] = Future{ 
    Thread.sleep(1000) 
    val num1 = Random.nextInt(10) 
    val num2 = Random.nextInt(10) 
    List(num1,num2) 
} 

現在的AA名單我想創作無限多的這樣的期貨和加入他們全都在結尾處(名單的一個未來)

AA功能

我打電話await.result用於測試目的

這適用於2升evels,但如何推廣N調用?

Await.result({ 
    nextValue.flatMap{ value1 => 
    nextValue.map{ value2 => 
     value1 ++ value2 
    } 
    } 
},1.minute) 
+0

如果每個'Future'僅在前一個完成後啓動,那麼使用'Future'有什麼意義?你可以在單一的「未來」中包裹一個「摺疊」或「流」,當停止條件滿足時它會完成嗎? – jwvh

回答

1
Future.sequence((0 to 100).map(_ => nextValue)).map(_.flatten) 

用法:

scala> Future.sequence((0 to 100).map(_ => nextValue)).map(_.flatten) 
res3: scala.concurrent.Future[scala.collection.immutable.IndexedSeq[Int]] = [email protected] 

scala> Await.result(res3, duration.Duration.Inf) 
res4: scala.collection.immutable.IndexedSeq[Int] = Vector(5, 4, 3, 0, 4, 6, 0, 8, 0, 0, 4, 6, 2, 7, 4, 9, 8, 8, 6, 9, 1, 4, 5, 5, 8, 2, 2, 7, 6, 0, 5, 6, 6, 5, 9, 6, 3, 5, 7, 1, 3, 2, 5, 3, 3, 1, 8, 4, 6, 7, 5, 1, 3, 5, 7, 4, 1, 5, 9, 4, 5, 0, 1, 8, 5, 0, 0, 7, 4, 2, 4, 2, 2, 0, 4, 1, 6, 3, 8, 2, 1, 3, 5, 5, 8, 3, 6, 1, 3, 2, 9, 4, 9, 4, 7, 5, 7, 8, 7, 9, 5, 2, 5, 0, 2, 5, 6, 8, 6, 2, 3, 2, 0, 8, 9, 3, 9, 2, 7, 5, 1, 7, 1, 1, 8, 6, 8, 0, 5, 5, 6, 0, 8, 8, 3, 6, 4, 2, 7, 1, 0, 3, 3, 3, 3, 2, 8, 7, 3, 3, 5, 1, 6, 3, 3, 7, 8, 9, 9, 9, 1, 9, 9, 8, 1, 1, 5, 8, 1, 1, 7, 6, 3, 2, 5, 0, 4, 3, 0, 9, 9, 1, 2, 0, 3, 6, 2, 6, 8, 6, 6, 3, 9, 7, 1, 3, 5, 9, 6, 5, 6, 2) 

或用scalaz /貓:

//import scalaz._,Scalaz._ 
// --or-- 
//import cats.syntax.traverse._ 
//import cats.std.list._ 
//import cats.std.future._ 

(0 to 100).toList.traverseM(_ => nextValue) 

Eplanation從here

traverseM(f)爲equival要穿過(f).map(_。join),其中連接是 拼合的名稱。這是非常有用的一種 「揭 flatMap」:


如果你需要一些條件,仍需要保持異步,您可以使用FS2:

import fs2._ 
import fs2.util._ 

def nextValue: Task[List[Int]] = Task.delay{ 
    import scala.util.Random 
    val num1 = Random.nextInt(10) 
    val num2 = Random.nextInt(10) 
    if(num1 > 5) List(num1,num2) else List() 
} 
Stream.repeatEval(nextValue).takeWhile(_.size > 0).runLog.map(_.flatten).unsafeRun 

https://github.com/functional-streams-for-scala/fs2/blob/series/0.9/docs/guide.md

同樣可以實現與迭代:

貓:https://github.com/travisbrown/iteratee 或scalaz-iteratee包

一般來說,你可以用fold,因爲它實際上是unfold並且在斯卡拉爲展開沒有很好的支持標準庫的Stream不能一概而論了一個單子/ ApplicativeFunctor(如不實現這個EnumeratorT確實) - 您只能在每個展開步驟中通過執行Await.result來檢查條件。

+0

我以爲OP正在尋找一個由退出條件決定的長度集合,即得到'nextValue'直到我們得到終點結果。 – jwvh

+0

你是對的,我沒有仔細閱讀這個問題 - 將更新我的回答 – dk14

+0

是的...我想測試getNext的結果,看看它是否有效,如果不是有效的,終止。這可能嗎? –