This is the third of several posts describing protips for
For the previous post, click here.
Unapplying Future.apply (sometimes)
I quite frequently encounter code which looks a bit like this:
import scala.concurrent._ def doSomething(someParam: SomeType)(implicit ec: ExecutionContext): Future[ResultType] = if (someParam == SomeValue) Future(SomeConstant) else Future(performSomeCalculation())
So what’s wrong with that? From a correctness point-of-view: nothing. However, if performance is a part of correctness—or at the very least part of availability—then understanding the implications, and alternatives, might be interesting!
Let’s start with: what does
According to its ScalaDoc, it does the following:
Starts an asynchronous computation and returns a Future instance with the result of that computation.
Alright, so it “starts a computation”. Furthermore the scaladoc says:
The following expressions are equivalent:
val f1 = Future(expr)
val f2 = Future.unit.map(_ => expr)` The result becomes available once the asynchronous computation is completed.
Interesting! So whenever you write
Future(something) it is actually equivalent to having written
Future.unit.map(_ => something).
So the problem with the code is that we’re—needlessly—starting an asynchronous computation in order to create a
Future with an already known value.
What can we do instead of
Future companion object sports 3 additional types of “constructors” for values of
Creates an already completed Future with the specified result.
Creates an already completed Future with the specified exception.
Creates an already completed Future with the specified result or exception.
Armed with this knowledge, we can rewrite the example as follows:
import scala.concurrent._ def doSomething(someParam: SomeType)(implicit ec: ExecutionContext): Future[ResultType] = if (someParam == SomeValue) Future.successful(SomeConstant) else Future(performSomeCalculation())
This avoids starting an asynchronous computation in the case where
someParam == SomeValue.
Future.fromTry when you need to create an instance of
Future and you already have the value.
Click here for the next part in this blog series.