我正在尝试使用for表达式迭代列表,然后使用返回Future的实用程序对每个元素进行转换。长话短说,它不编译,我想了解原因。我读过类似的this question,这是一个很好的帮助,但我想要做的更简单,更令人困惑的是为什么它不起作用。我正在尝试做类似的事情:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
val numberList = List(1, 2, 3)
def squareInTheFuture(number: Int): Future[Int] = Future { number * number}
val allTheSquares = for {
number <- numberList
square <- squareInTheFuture(number)
} yield { square }
我得到的是:
错误:类型不匹配; 发现:scala.concurrent.Future [Int] 必需:scala.collection.GenTraversableOnce [?] square&lt; - squareInTheFuture(number) ^
有人可以帮助我理解为什么这不起作用,最好的选择是什么?
答案 0 :(得分:9)
Future
companion object有一个traverse
方法可以完全按照您的要求执行:
val allTheSquares: Future[List[Int]] =
Future.traverse(numberList)(squareInTheFuture)
这将异步启动所有计算并返回将在所有这些期货完成后完成的未来。
答案 1 :(得分:8)
flatMap
要求numberList
和squareInTheFuture(number)
的类型构造函数相同(以模块集合库的隐式转换为模)。这不是这种情况。相反,这是一次遍历:
val allSquaresInTheFuture: Future[List[Int]] =
Future.traverse(numberList)(squareInTheFuture)
答案 2 :(得分:3)
@Lee是对的。另外,如果您尝试进行并行计算:
val numberList = List(1, 2, 3)
val allTheSquares = numberList.par.map(x => x * x)(breakOut)
如果你真的想要Future
:
val allTheSquares: Future[List[Int]] = Future.traverse(numberList)(squareInTheFuture)
答案 3 :(得分:2)
您的理解与
相同val allTheSquares = numberList.flatMap(number => squareInTheFuture(number))
flatMap
要求它的参数函数返回GenTraversableOnce[Int]
,但是你的返回Future[Int]
,因此不匹配。
答案 4 :(得分:1)
将<-更改为=可以。这样,就不会在Future对象上调用flatmap / map。
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
val numberList = List(1, 2, 3)
def squareInTheFuture(number: Int): Future[Int] = Future { number * number}
val allTheSquares = for {
number <- numberList
square = squareInTheFuture(number)
} yield { square }
阅读this帮助我了解了收益率的工作原理。