Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

scala

akka

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?

like image 798
Phil Avatar asked Jul 14 '11 04:07

Phil


People also ask

What is the difference between MAP and flatMap in Scala?

Now, map transforms an RDD of length N into another RDD of length N. But flatMap (loosely speaking) transforms an RDD of length N into a collection of N collections, then flattens these into a single RDD of results. The input and output RDDs will therefore typically be of different sizes for flatMap .

What is flatMap in Scala?

flatMap() method is method of TraversableLike trait, it takes a predicate, applies it to each element of the collection and returns a new collection of elements returned by the predicate.

How does future work in Scala?

Future represents a result of an asynchronous computation that may or may not be available yet. When we create a new Future, Scala spawns a new thread and executes its code. Once the execution is finished, the result of the computation (value or exception) will be assigned to the Future.

Is Scala future blocking?

By default, futures and promises are non-blocking, making use of callbacks instead of typical blocking operations. To simplify the use of callbacks both syntactically and conceptually, Scala provides combinators such as flatMap , foreach , and filter used to compose futures in a non-blocking way.


3 Answers

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

like image 110
paradigmatic Avatar answered Oct 18 '22 09:10

paradigmatic


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] 
like image 35
Alexey Romanov Avatar answered Oct 18 '22 09:10

Alexey Romanov


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

like image 1
Mahesh Avatar answered Oct 18 '22 09:10

Mahesh