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

发布于 2024-11-23 18:55:19 字数 525 浏览 3 评论 0原文

在普通的 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 future 中的 map 和 flatMap 之间有什么区别吗?

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?

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:"

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

自找没趣 2024-11-30 18:55:19

在“正常”Scala 中(如您所说),map 和 flatMap 与列表无关(例如检查 Option)。

阿列克谢给了你正确的答案。现在,如果你想知道为什么我们需要两者,它允许在编写 future 时使用漂亮的 for 语法。给定类似的内容:

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

编译器将其重写为:

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

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

假设现在仅使用映射,编译器可以执行以下操作:

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

然而,结果应该是 Future[Future[A]] 类型。这就是为什么你需要将其压平。

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

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

In "normal" Scala (as you say), map and flatMap have nothing to do with Lists (check Option for example).

Alexey gave you the correct answer. Now, if you want to know why we need both, it allows the nice for syntax when composing futures. Given something like:

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].

Suppose now only map was used, the compiler could have done something like:

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.

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

澜川若宁 2024-11-30 18:55:19

有人可以解释一下 Akka future 中的 map 和 flatMap 之间有什么区别吗?

类型基本上是:

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

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

Can someone please explain what is the difference between map and flatMap here in Akka futures?

The type, basically:

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

map[A](f: T => A): Future[A] 
在巴黎塔顶看东京樱花 2024-11-30 18:55:19

我在这里粘贴这两种方法的实现。
英文术语的差异如下
并返回函数的结果作为新的 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
   }

与实现的区别在于,当 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

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.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文