I know a lot of reasons for Scala Future to be better. Are there any reasons to use Twitter Future instead? Except the fact Finagle uses it.
2 Answers
Disclaimer: I worked at Twitter on the Future implementation. A little bit of context, we started our own implementation before Scala had a "good" implementation of Future
.
Here're the features of Twitter's Future
:
- Some method names are different and Twitter's
Future
has some new helper methods in the companion.
e.g. Just one example: Future.join(f1, f2)
can work on heterogeneous Future types.
Future.join(
Future.value(new Object), Future.value(1)
).map {
case (o: Object, i: Int) => println(o, i)
}
o
and i
keep their types, they're not casted into the least common supertype Any
.
A chain of onSuccess is guaranteed to be executed in order: e.g.:
f.onSuccess { println(1) // #1 } onSuccess { println(2) // #2 }
#1 is guaranteed to be executed before #2
The Threading model is a little bit different. There's no notion of ExecutionContext, the Thread that set the value in a Promise (Mutable implementation of a Future) is the one executing all the computations in the future graph. e.g.:
val f1 = new Promise[Int] f1.map(_ * 2).map(_ + 1) f1.setValue(2) // <- this thread also executes *2 and +1
There's a notion of interruption/cancellation. With Scala's Futures, the information only flows in one direction, with Twitter's Future, you can notify a producer of some information (not necessarily a cancellation). In practice, it's used in Finagle to propagate the cancellation of a RPC. Because Finagle also propagates the cancellation across the network and because Twitter has a huge fan out of requests, this actually saves lots of work.
class MyMessage extends Exception val p = new Promise[Int] p.setInterruptHandler { case ex: MyMessage => println("Receive MyMessage") } val f = p.map(_ + 1).map(_ * 2) f.raise(new MyMessage) // print "Receive MyMessage"
Until recently, Twitter's Future were the only one to implement efficient tail recursion (i.e. you can have a recursive function that call itself without blowing up you call stack). It has been implemented in Scala 2.11+ (I believe).

- 43,056
- 28
- 105
- 132

- 15,158
- 6
- 38
- 42
-
Cancellation makes sense, especially if you issue duplicate requests to fight latency... – Sergey Alaev Oct 08 '15 at 07:18
-
Hi there Steve. Long time no see :-D. Hope everything's well for you. Concerning the question, the part on the threading model is a huge difference indeed, I forgot about that one. With scala's `Future` we have to request an implicit execution context every time we want to merely map on a future even for trivial thins such as adding a log, whereas with Twitter's `Future`we can piggyback on the original future's thread. – Régis Jean-Gilles Oct 08 '15 at 07:47
-
Well, I have no idea why Scala does not provide ExecutionContext that works like Twitter's LocalScheduler. – Sergey Alaev Oct 08 '15 at 08:28
As far as I can tell the main difference that could go in favor of using Twitter's Future
is that it can be cancelled, unlike scala's Future
.
Also, there used to be some support for tracing the call chains (as you probably know plain stack traces are close to being useless when using Futures). In other words, you could take a Future and tell what chain of map
/flatMap
produced it. But the idea has been abandoned if I understand correctly.

- 32,541
- 5
- 83
- 97
-
Yep, but they deprecated cancel() some time ago in favor of less obligatory raise(). Did you use cancel() in production code? Was it useful? – Sergey Alaev Oct 07 '15 at 09:00
-
I have not used it partly because I did not want to be stuck with non standard twitter's `Future`. But it's easy to see uses for it. Say that you spawn a few futures concurrently and then join their results through `Future.sequence` to build a final result. If any one fail you'd like to fail fast, in other words to cancel all the other futures in order to save yourself from useless computations. Arguably, the standard/better/less brittle way to handle this situation (without relying on future cancelling) is to use actors instead. – Régis Jean-Gilles Oct 07 '15 at 09:06
-
As for `cancel` being deprecated in favor of `raise`, the rationale still holds: that's something that is not in scala's `Future` and *might* make you reach for Twitter's version. – Régis Jean-Gilles Oct 07 '15 at 09:11
-
@RégisJean-Gilles By the way, "If any one fail you'd like to fail fast" -- that's not a problem for the standard `Future.sequence`, because it doesn't complete until all the `Future`s in the sequence complete, even if some of them fail early. – Kolmar Oct 07 '15 at 10:05
-
1"it doesn't complete until all the Futures in the sequence complete, even if some of them fail early." I'm saying that sometimes you'd precisely like to not only complete (with failure) the final future when one of the input future fails, but also stop all the future's execution as soon as any has already failed. `Future.sequence` certainly does not do that. – Régis Jean-Gilles Oct 07 '15 at 12:09