在 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 03:12:47  来源:igfitidea点击:

In Scala Akka futures, what is the difference between map and flatMap?

scalaakka

提问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