Scala中的未来构成与响应的分块

时间:2015-12-12 00:30:13

标签: scala

我想我已经理解了未来的构成如何运作但我很困惑如何从第一个未来的大部分回应中引用下一个未来。 假设第一个未来返回一个整数列表,列表很大。我想一次将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
            ^

返回类型必须是Future [?]所以我可以通过移动第二个未来来产生一部分来修复它:

val res = for {
  list <- a
} yield {
  val temp = for {
    chunked <- list.grouped(2).toList
  } yield f(chunked)
  Future.sequence(temp)
}

我觉得它现在失去了它的优雅,因为它变得嵌套(在第一种方法中看到两个用于理解而不是一个)。有没有更好的方法来实现同样的目标?

2 个答案:

答案 0 :(得分:2)

考虑

a.map { _.grouped(2).toList }.flatMap { Future.traverse(_)(f) }

或者,如果由于某种原因你只使用for理解,那么这就是如何,没有&#34;作弊&#34; :)

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

或者,没有for理解:

a
.map { _.grouped(2).toList }
.map(processChunks)
.flatMap { Future.traverse(_)(f) }

答案 1 :(得分:1)

您无法将$(".glyphicon-remove").click(function(){ $(this).parent().hide(); }); Future混合在一起进行理解。所有涉及的对象必须属于同一类型。另外,在您的工作示例中,结果值List的类型为res,这可能不是您想要的。

Future[Future[List[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
相关问题