2016-07-01 36 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的结果,看看它是否有效,如果不是有效的,终止。这可能吗? –