scala期货顺序懒惰执行

时间:2016-06-22 08:44:21

标签: scala future

我有一个iterable期货,每个期货都会返回一个序列:Iterable[Future[Seq[Int]]]因此,我需要一个序列,它是从期货返回的序列的串联:{{1} }。

问题是我只需要生成序列的第一个Seq[Int]元素,所以我不总是需要执行所有的期货。我也事先不知道需要执行多少期货来实现它(也许第一个将足够回归,也许我们必须全部执行)。

显然,我需要按顺序执行我的功能。我可以做foreach和break / return,但我想以功能的方式表达它。

2 个答案:

答案 0 :(得分:2)

以下似乎有效且“看起来”功能正常。我对这将如何实际执行或在幕后行动知之甚少。

这很容易被打成一个def,其中硬编码4传递一个参数。

我认为我应该返回5个元素,即使只有4个被要求,因为对中间未来的评估需要以任何一种方式进行。删除多余的元素应该很简单。

val f = Iterable(Future(Seq(1,2,3)), Future(Seq(4,5)), Future(Seq(6,7,8)))

val output = f.foldLeft(Future(Seq.empty[Int])){(previous, next) =>
    previous.flatMap{pSeq =>
        if(pSeq.length >= 4) {
            Future(pSeq)
        } else {
            next.map(nSeq => pSeq ++ nSeq)
        }
    }
}

println(Await.result(output, Duration.Inf)) //List(1,2,3,4,5)

我不喜欢的是将pSeq包装在Future中以保持一致的类型。

编辑:只是对viktor答案的回应(由于代表不够高,我无法发表评论,这对我的答案略有增加)。

即使Viktor的回答更容易阅读,它也必须等待所有期货完成,即使它们不是必需的。

例如,用以下内容替换我的f:

val f = Iterable(Future(Seq(1,2,3)), Future(Seq(4,5)), Future(throw new Exception))

它仍然可以工作,Viktor的调用Future.sequence将一个Iterable [Future []]转换为Future [Iterable []],因此必须完成所有这些。

答案 1 :(得分:1)

要么使用Future.fold:

scala> import scala.concurrent._

scala> import ExecutionContext.Implicits.global

scala> Future.fold(Iterable(Future(Seq(1,2,3)), Future(Seq(4,5)), Future(Seq(6,7,8))))(Seq.empty[Int])( (prev, cur) => if(prev.size >= 4) prev else prev ++ cur) foreach println

List(1, 2, 3, 4, 5)

scala>

或者您查看Future.fold的实现方式并添加退出条件。 (基本上是一个foldUntil)