在Scala Akka期货中,map和flatMap有什么区别?

时间:2011-07-14 04:00:07

标签: scala akka

普通Scala map和flatMap中的

不同之处在于flatMap将返回一个可迭代的数据展平到列表中。 但是在Akka文档中,map和flatMap似乎做了不同的事情?

http://akka.io/docs/akka/1.1/scala/futures.html

它说“通常情况下这很有效,因为这意味着运行快速功能的开销非常小。如果该功能有可能需要花费很多时间来处理它,那么这可能会更好同时完成,为此我们使用flatMap:“

val f1 = Future {
  "Hello" + "World"
}

val f2 = f1 flatMap {x =>
  Future(x.length)
}

val result = f2.get()

有人可以解释Akka期货中地图和flatMap之间的区别吗?

3 个答案:

答案 0 :(得分:60)

在“普通”Scala中(如你所说),map和flatMap与列表无关(例如选中Option)。

Alexey给了你正确的答案。现在,如果你想知道为什么我们需要两者,它在编写期货时允许使用漂亮的for语法。给出类似的东西:

val future3 = for( x <- future1;
                   y <- future2 ) yield ( x + y )

编译器将其重写为:

val future3 = future1.flatMap( x => future2.map( y => x+y ) )

如果您遵循方法签名,您应该看到该表达式将返回Future[A]类型的内容。

假设现在只使用了map,编译器可以做类似的事情:

val future3 = future1.map( x => future2.map( y => x+y ) )

但是,结果应该是Future[Future[A]]类型。这就是你需要压扁它的原因。

要了解背后的概念,这是我读过的最好的介绍之一:

http://www.codecommit.com/blog/ruby/monads-are-not-metaphors

答案 1 :(得分:35)

  

有人可以解释Akka期货中地图和flatMap之间的区别吗?

类型,基本上:

flatMap[A](f: T => Future[A]): Future[A] 

map[A](f: T => A): Future[A] 

答案 2 :(得分:1)

我在这里粘贴了两种方法的实现。 英语术语的差异如下 并将函数的结果作为新的未来返回

         /** 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
   }

从实现开始,不同之处在于,当promise完成时,flatMap实际上会调用带有结果的函数。

case Success(v) => try f(v) match 

阅读一篇好文章:http // danielwestheide.com / blog / 2013/01/16 / the-neophytes-guide-to-scala-part-9-promises-and-futures-in-practice.html < / p>