Scala中具有分块响应的未来合成

Scala中具有分块响应的未来合成,scala,Scala,我想我已经理解了未来的构图是如何工作的,但我不知道如何在第一个未来的响应块上调用下一个未来。 假设第一个future返回一个整数列表,该列表非常大。我想对一次包含2个元素的列表应用一些函数。我该怎么做 这个例子总结了我的困境: val a = Future(List(1,2,3,4,5,6)) def f(a: List[Int]) = Future(a map (_ + 2)) val res = for { list <- a chunked <- list.grouped(

我想我已经理解了未来的构图是如何工作的,但我不知道如何在第一个未来的响应块上调用下一个未来。 假设第一个future返回一个整数列表,该列表非常大。我想对一次包含2个元素的列表应用一些函数。我该怎么做

这个例子总结了我的困境:

val a = Future(List(1,2,3,4,5,6))
def f(a: List[Int]) = Future(a map (_ + 2))
val res = for {
 list <- a
 chunked <- list.grouped(2).toList
} yield f(chunked)

<console>:14: error: type mismatch;
 found   : List[scala.concurrent.Future[List[Int]]]
 required: scala.concurrent.Future[?]
        chunked <- list.grouped(2).toList
            ^
val a=未来(列表(1,2,3,4,5,6))
def(a:List[Int])=未来(一个映射(u2))
val res=用于{

list您不能将
Future
list
混合在一起以便于理解。所有涉及的对象必须是同一类型。此外,在您的工作示例中,您的结果值
res
的类型为
Future[Future[list[Int]]]
,这可能不是您想要的

import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
a: scala.concurrent.Future[List[Int]] = scala.concurrent.impl.Promise$DefaultPromise@3bd3cdc8
f: (a: List[Int])scala.concurrent.Future[List[Int]]

scala> val b: Future[List[List[Int]]] = a.map(list => list.grouped(2).toList)
b: scala.concurrent.Future[List[List[Int]]] = scala.concurrent.impl.Promise$DefaultPromise@74db196c

scala> val res: Future[List[List[Int]]] = b.flatMap(lists => Future.sequence(lists.map(f)))
res: scala.concurrent.Future[List[List[Int]]] = scala.concurrent.impl.Promise$DefaultPromise@28f9873c
用以理解

for {
    b ← a.map(list ⇒ list.grouped( 2 ).toList)
    res ← Future.sequence(b.map(f))
} yield res
考虑

a.map { _.grouped(2).toList }.flatMap { Future.traverse(_)(f) }
或者,如果出于某种原因,你决定只使用
进行理解,下面是如何在不“作弊”的情况下:


当你说
所有涉及的对象必须是同一类型时
基本上意味着
a你可以删除
映射
并在
c下面添加一行新行,感谢这个解决方案的有效性!但是我认为,扩展这个解决方案变得非常困难。比如,如果我想进一步处理分块列表,然后应用
f
这让它变得很难:(嗯,你越想“扩展”东西,它通常就变得越难……这就是程序员赚大钱的原因。)我的意思是,做更多的处理比做更少的处理更难,这并不奇怪,是吗?我编辑了答案,以展示如何做的总体思路。
a.map { _.grouped(2).toList }.flatMap { Future.traverse(_)(f) }
for {
  b <- a
  c <- Future.traverse(b.grouped(2).toList)(f)
} yield c
for {
   b <- a
   chunks = b.grouped(2).toList
   processedChunks = processChunks(chunks)
   c <- Future.traverse(processedChunks)
} yield c
a
.map { _.grouped(2).toList }
.map(processChunks)
.flatMap { Future.traverse(_)(f) }