【发布时间】:2013-08-05 07:25:28
【问题描述】:
我有时会发现自己有一些 Stream[X] 和 function X => Future Y,我想将它们合并到 Future[Stream[Y]] 中,但我似乎找不到办法.例如,我有
val x = (1 until 10).toStream
def toFutureString(value : Integer) = Future(value toString)
val result : Future[Stream[String]] = ???
我试过了
val result = Future.Traverse(x, toFutureString)
它给出了正确的结果,但似乎在返回 Future 之前消耗了整个流,这或多或少地失败了
我试过了
val result = x.flatMap(toFutureString)
但这不能用type mismatch; found : scala.concurrent.Future[String] required: scala.collection.GenTraversableOnce[?]编译
val result = x.map(toFutureString)
返回有点奇怪和无用的Stream[Future[String]]
我应该怎么做才能解决问题?
编辑:我没有卡在Stream 上,我同样会对Iterator 上的相同操作感到满意,只要它在开始处理头部之前不会阻止评估所有项目
Edit2:我不能 100% 确定 Future.Traverse 构造是否需要在返回 Future[Stream] 之前遍历整个流,但我认为确实如此。如果没有,这本身就是一个很好的答案。
Edit3:我也不需要结果是有序的,无论返回的流或迭代器是什么顺序,我都可以。
【问题讨论】:
-
请注意,我已提交an issue 以跟进我在下面的回答。
-
啊,太棒了@TravisBrown。我想自己做,但我找不到登录 Jira 的方法
-
有点不清楚 - 你想避免将“toFutureString”应用于集合中的所有元素......?似乎简单地创建一个未来不应该有太多的开销。如果“列表”中的其余项目是 thunk,什么会触发它们的评估?完成未来列表中的上一个?我可以在 Scala 中找到的所有序列/遍历操作似乎对单个列表元素都很严格。
-
@pdxleif 好问题,我想这基本上就是我的问题归结为。我知道我只想要一个
[Future[Stream[String]],但我不知道每次评估应该如何以及何时进行(如果我这样做了,我不会问;)。在我看来,thunk 和 Future 是(可能是错误的)相似的东西,所以我想我想加入或组合它们? -
我认为它们很相似。 Travis 提到的 Scalaz 遍历确实立即为您提供了 Future[Stream[String]],其中(单个)Future 直到整个 Stream 必须应用 toFutureStream 并运行完成后才会完成。我想我对用例有点好奇——通常当我有一系列涉及等待的 IO 计算时,它们之间没有数据依赖关系,我想以并行方式急切地开始它们的执行。 Stream 的 scalaz 遍历实例似乎给出了与折叠带有 .flatMap 的常规列表所获得的效果相似的效果。