是否有一种更惯用的方式来编写反复调用的映射(而不使用flatMap)?
请参阅以下示例:
val futureJson : Future[Seq[JsValue]] = futureBlogList.map(
blogList => blogList.map(
blog => Json.obj("id" -> blog.id, "title" -> blog.title)))
val futureResult : Future[Result] = futureJson.map(jsList => Ok(JsArray(jsList)))这是一个正在运行的函数,在本例中需要返回一个FutureResult。
我试过使用“用于理解”,但没有找到flatMap的应用程序。我使用flatMap的尝试使我不得不使用FutureNothing。
val futureJson : Future[Nothing] = for {
blogList : Seq[Blog] <- futureBlogList
blog : Blog <- blogList
} yield {
Json.obj("id" -> blog.id, "title" -> blog.title)
}发布于 2015-07-15 17:55:47
flatMaps和一个map函数的组合。Seq[...]、Option[...]、.)您的工作解决方案由两个map、一个Future和一个Seq组成,因此不能将其转换为用于理解的(很好)。
关于理解的更多信息(以及与flatMap/map的转换)可以在http://www.artima.com/pins1ed/for-expressions-revisited.html和this question中找到。
如果您真的想使用a for理解而不是两个map,我们可以(作为一个教育练习)将第一个map转换为flatMap。然后,使用blogList的函数应该返回一个Future
futureBlogList.flatMap(blogList =>
Future.successful(
blogList.map(blog => Json.obj("id" -> blog.id, "title" -> blog.title))
)
)我们可以将第二个map转换为一个for表达式:
futureBlogList.flatMap(blogList =>
Future.successful(
for (blog <- blogList) yield Json.obj("id" -> blog.id, "title" -> blog.title)
)
)
//.map(identity)为了理解,我们可以将其转化为以下(相当丑陋):
for {
blogList <- futureBlogList
jsonBlogs <- Future.successful(
for (blog <- blogList) yield Json.obj("id" -> blog.id, "title" -> blog.title)
)
) yield jsonBlogs发布于 2015-07-15 17:53:26
您的理解失败的原因是它在相同类型的容器上工作。在您的示例中,您将Future与集合混合在一起。的确,两者都有map,但它们是不同类型的容器,因此它们的map/flatmap链不能互操作,因此不能一起用于理解。如果你展开理解力,你就会得到
futurBlogList.flatMap { blogList =>
blogList.map { blog =>
Json.obj("id" -> blog.id, "title" -> blog.title)
}
}flatMap期望结果是一个Future[U],但是内部的map调用将返回一个Seq[JSList]。
最终的结果是,嵌套两种不同类型的map是表达构造的最惯用的方式。充其量,您可以将这两个调用组合成如下所示:
val futureResult : Future[Result] = futureBlogList.map { blogList =>
Ok(JsArray(
blogList.map( blog => Json.obj("id" -> blog.id, "title" -> blog.title))
))
}https://stackoverflow.com/questions/31434763
复制相似问题