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