我想迭代一个从未来获得的向量。我希望以下内容能够正常工作,但它会在user <- usersToReview
行上出现类型不匹配的编译器错误。
import scala.concurrent.{Await, Future}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Await
import scala.concurrent.duration._
object Main3 {
var counter = 0
val fUsersToReview: Future[Vector[String]] = Future {Vector("u1", "u2", "u3")}
def doIt(user: String): Future[Int] = {
counter = counter + 1
Future.successful(counter)
}
def main(args: Array[String]): Unit = {
val result:Future[Vector[Int]] = for {
usersToReview ← fUsersToReview
user ← usersToReview
msg_id ← doIt(user)
} yield {
msg_id
}
println(Await.result(result, 1.second))
}
}
以下作品,但看起来非常笨重。关于如何改进这个的建议?
def main(args: Array[String]): Unit = {
val result:Future[Vector[Int]] = (for {
usersToReview ← fUsersToReview
} yield {
Future.sequence(
for (u ← usersToReview) yield {
doIt(u)
}
)
}).flatMap(identity)
println(Await.result(result, 1.second))
}
}
答案 0 :(得分:0)
这是一个不使用for-comprehension
而只使用map
可能更干净的例子:
val result: Future[Vector[Int]] = fUsersToReview.map(_.map(doIt(_)))
对于Option
和Either
之类的内容,您可以使用OptionT和EitherT等monad转换器,但Vector
没有任何内容。< / p>
答案 1 :(得分:0)
感谢关于adrice727答案的见解,我已经找到了问题的解决方案。它涉及重构doIt
以获取向量。
通过将向量的处理转移到doIt
,向量出于for-comprehension。一旦它只处理期货,它就会按预期工作。
我稍微简化了我的原始帖子,因此以下内容包括for-comprehension中的另一个级别,doIt
实际上对它传递的数据做了一些事情。背景是fMaintainers
,fUsersToReview
和doIt
都在数据库上。
val fMaintainers: Future[Vector[String]] = Future {Vector("m1", "m2", "m3")}
val fUsersToReview: Future[Vector[String]] = Future {Vector("u1", "u2", "u3")}
def doIt(users: Vector[String], maintainers: Vector[String]): Future[Vector[(String, String)]] = {
Future.sequence(for (u ← users) yield {
Future.successful((u, maintainers.head))
})
}
val result: Future[Vector[(String, String)]] = for {
maintainers ← fMaintainers
usersToReview ← fUsersToReview
msg_id ← doIt(usersToReview, maintainers)
} yield {
msg_id
}
println(Await.result(result, 1.second))
最后,关注adrice727的建议,即有时候理解不是正确的工具,这里是地图:
val result:Future[Vector[(String, String)]] =
fMaintainers.flatMap { m ⇒ fUsersToReview.flatMap { u ⇒ doIt(u, m) } }