在 Scala Akka 期货中,map 和 flatMap 有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6688329/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In Scala Akka futures, what is the difference between map and flatMap?
提问by Phil
in normal Scala map and flatMap are different in that flatMap will return a iterable of the data flattened out into a list. However in the Akka documentation, map and flatMap seem to do something different?
在普通的 Scala 地图和 flatMap 中, flatMap 的不同之处在于 flatMap 将返回扁平化为列表的数据的可迭代对象。但是在 Akka 文档中, map 和 flatMap 似乎做了一些不同的事情?
http://akka.io/docs/akka/1.1/scala/futures.html
http://akka.io/docs/akka/1.1/scala/futures.html
It says "Normally this works quite well as it means there is very little overhead to running a quick function. If there is a possibility of the function taking a non-trivial amount of time to process it might be better to have this done concurrently, and for that we use flatMap:"
它说“通常这很有效,因为这意味着运行快速函数的开销很小。如果函数有可能花费大量时间来处理,最好同时完成,为此,我们使用 flatMap:”
val f1 = Future {
"Hello" + "World"
}
val f2 = f1 flatMap {x =>
Future(x.length)
}
val result = f2.get()
Can someone please explain what is the difference between map and flatMap here in Akka futures?
有人可以解释一下 Akka 期货中 map 和 flatMap 之间的区别吗?
回答by paradigmatic
In "normal" Scala (as you say), map and flatMap have nothing to do with Lists (check Option for example).
在“普通”Scala(如您所说)中,map 和 flatMap 与列表无关(例如,检查 Option)。
Alexey gave you the correct answer. Now, if you want to know why we need both, it allows the nice forsyntax when composing futures. Given something like:
阿列克谢给了你正确的答案。现在,如果你想知道为什么我们需要两者,它允许for在编写期货时使用漂亮的语法。给出类似的东西:
val future3 = for( x <- future1;
y <- future2 ) yield ( x + y )
The compiler rewrites it as:
编译器将其重写为:
val future3 = future1.flatMap( x => future2.map( y => x+y ) )
If you follow the method signature, you should see that the expression will return something of type Future[A].
如果您遵循方法签名,您应该会看到表达式将返回类型为 的内容Future[A]。
Suppose now only map was used, the compiler could have done something like:
假设现在只使用了 map,编译器可以做如下事情:
val future3 = future1.map( x => future2.map( y => x+y ) )
However, the result whould have been of type Future[Future[A]]. That's why you need to flatten it.
但是,结果本来应该是 类型的Future[Future[A]]。这就是为什么你需要把它弄平。
To learn about the concept behind, here is one the best introduction I've read:
要了解背后的概念,这是我读过的最好的介绍之一:
http://www.codecommit.com/blog/ruby/monads-are-not-metaphors
http://www.codecommit.com/blog/ruby/monads-are-not-metaphors
回答by Alexey Romanov
Can someone please explain what is the difference between map and flatMap here in Akka futures?
有人可以解释一下 Akka 期货中 map 和 flatMap 之间的区别吗?
The type, basically:
类型,基本上:
flatMap[A](f: T => Future[A]): Future[A]
map[A](f: T => A): Future[A]
回答by Mahesh
I am pasting the implementation of the two methods here. the difference in english terms is below and returns the result of the function as the new future
我在这里粘贴这两种方法的实现。英文术语的差异如下, 并返回函数的结果作为新的未来
/** Creates a new future by applying a function to the successful result of
* this future. If this future is completed with an exception then the new
* future will also contain this exception.
*
* $forComprehensionExamples
*/
def map[S](f: T => S)(implicit executor: ExecutionContext): Future[S] = { // transform(f, identity)
val p = Promise[S]()
onComplete { v => p complete (v map f) }
p.future
}
/** Creates a new future by applying a function to the successful result of
* this future, and returns the result of the function as the new future.
* If this future is completed with an exception then the new future will
* also contain this exception.
*
* $forComprehensionExamples
*/
def flatMap[S](f: T => Future[S])(implicit executor: ExecutionContext): Future[S] = {
import impl.Promise.DefaultPromise
val p = new DefaultPromise[S]()
onComplete {
case f: Failure[_] => p complete f.asInstanceOf[Failure[S]]
case Success(v) => try f(v) match {
// If possible, link DefaultPromises to avoid space leaks
case dp: DefaultPromise[_] => dp.asInstanceOf[DefaultPromise[S]].linkRootOf(p)
case fut => fut.onComplete(p.complete)(internalExecutor)
} catch { case NonFatal(t) => p failure t }
}
p.future
}
From implementation the difference is that flatMap actually calls the function with result when the promise completes.
从实现来看,不同之处在于 flatMap 实际上在 promise 完成时调用了带有结果的函数。
case Success(v) => try f(v) match
For a great article read: http//danielwestheide.com/blog/2013/01/16/the-neophytes-guide-to-scala-part-9-promises-and-futures-in-practice.html
阅读一篇很棒的文章:http://danielwestheide.com/blog/2013/01/16/the-neophytes-guide-to-scala-part-9-promises-and-futures-in-practice.html

