Future.transform in Scala 2.12
09 Feb 2017Scala 2.12 added a few improvements to scala.concurrent.Future
. Here I am going to take a quick look at the new transform
and transformWith
methods. First, let’s see the old method signature:
def transform[S](s: (T) ⇒ S, f: (Throwable) ⇒ Throwable): Future[S]
Creates a new future by applying the ‘s’ function to the successful result of this future, or the ‘f’ function to the failed result.
The main shortcoming of this method is related to f
. Even though we can handle the exception case, the signature Throwable ⇒ Throwable
bounds the future to fail once an exception is thrown.
The new method is much more powerful in this regard:
def transform[S](f: (Try[T]) ⇒ Try[S]): Future[S]
Creates a new Future by applying the specified function to the result of this Future.
By providing a function Try[T] ⇒ Try[S]
we can handle both Success
and Failure
cases and transform them in any way we like. For example, if we want a future to always complete successfully we can now write it like this:
scala> val future = Future(throw new Exception("Oops"))
scala> future.transform {
case Success(_) => Try("OK")
case Failure(_) => Try("KO")
}
res0: scala.concurrent.Future[String] = Future(Success(KO))
To achieve a similar behaviour in Scala 2.11 we would have to combine map
and recover
statements or use onComplete
in a Promise.
The new transformWith
unifies flatMap
and recoverWith
in a similar way. Here is the signature:
def transformWith[S](f: Try[T] => Future[S]): Future[S]
Creates a new Future by applying the specified function, which produces a Future, to the result of this Future.
If you want to transform your result and you need to return another Future
instead of a Try
, go for transformWith
.
Make sure to check the blog posts from Viktor Klang for more information about Futures on Scala 2.12 and, as always, check the documentation for details.