Chaining Futures/ListenableFuture incongruity

536 views
Skip to first unread message

Emily Soldal

unread,
Jun 14, 2012, 8:04:07 AM6/14/12
to guava-...@googlegroups.com
I was writing some slides for a guava presentation yesterday and came across some "weirdness" in the way the Futures API is set up

To execute futures as a sequence of operations, taking the result of the preceding future as the input for the following you would have to do something along the lines of:

ListenableFuture<A> a = get();

ListenableFuture<B> b = Futures.transform(a, new AsyncFunction<A,B>() {
    public ListenableFuture<B> apply(A input) {
        // ....
    }
});


*.transform means "give me a view" in Guavaneese, but this doesn't actually give you a view so much as add a listener to the parent future. I'm actually sort of happy with how it works right now, but the method names really had me stumped for a while! Has anyone else felt that this is "weird"? 

Also, FluentListenableFuture soon? :D

- Emily

Chris Povirk

unread,
Jun 14, 2012, 10:51:09 AM6/14/12
to Emily Soldal, guava-...@googlegroups.com
Agreed: "transform" means something different for Futures than it does
for Lists, Maps, etc. If we were starting from scratch, we'd probably
name one of the two concepts differently, even if only something like
"transformedView." Ironically, the Futures method that behaves like
Lists.transform doesn't get that name:

https://www.corp.google.com/~engdocs/nonconf/java/common/com/google/common/util/concurrent/Futures.html#lazyTransform%28java.util.concurrent.Future,%20com.google.common.base.Function%29


FluentListenableFuture is on our list of things to try. Arguably it
has a better case than common.base classes like FluentPredicate, but
we happen to have written those ones first, so it may be a while. A
few comments while it's on my mind:

- Some Futures methods apply only to multiple Futures or certain types
of Futures, and others may one day be removed. The ones I'd feel most
comfortable seeing replicated to FluentListenableFuture are probably
addCallback, get, getUnchecked, transform (both), and withFallback.

- We could take this opportunity to "fix" the generics on transform,
replacing "? extends O" with plain "O" on the transform parameters.
(It's not clear that that's the right decision overall, but it's the
pattern we've tried to follow elsewhere; the Futures.transform methods
slipped through.)

- One crazy idea is to allow a FLF to have an Executor associated with
it, one that would be used by calls to transform, etc. This would
mean we would no longer need 2 copies of each method. I'm kind of
nervous about this, since it makes Futures.transform(future, function)
and future.transform(function) behave differently, so I'm leaning
against it, but I thought I'd throw it out there.

If you're interested in putting together a CL to speed things along
(though the review may be a bit slow and nitpicky), I could take a
look.

Christian Edward Gruber

unread,
Jun 14, 2012, 12:09:22 PM6/14/12
to Chris Povirk, Emily Soldal, guava-...@googlegroups.com
At the risk of Kevin's irritation, I'll say this. For something like this, I'm inclined to actually create a transformView() method on Lists/Maps/etc., for clarity, and deprecate the old transform() method. At least it would capture our usage intentions more clearly, and call to mind the distinction.

Christian

Louis Wasserman

unread,
Jun 14, 2012, 12:29:18 PM6/14/12
to Christian Edward Gruber, Chris Povirk, Emily Soldal, guava-...@googlegroups.com
...Yeah, I'm going to rise to the bait.

If we added the word "view" to every view operation Guava provided, we'd be here all day.  There are a lot.

I'd much rather prefer to fix Futures to follow the precedent, than to add that much cruft to so many, such commonly used methods.

Christian Edward Gruber

unread,
Jun 19, 2012, 4:48:56 PM6/19/12
to Louis Wasserman, Chris Povirk, Emily Soldal, guava-...@googlegroups.com
I think I just got told. :D  

And, don't worry… in practice, I concede.  I just wish it were otherwise.

Christian

Emily Soldal

unread,
Jun 19, 2012, 5:15:02 PM6/19/12
to Christian Edward Gruber, Louis Wasserman, Chris Povirk, guava-...@googlegroups.com
I have a CL in the works for this, but I still can't think of anything better than "transform" even though it sounds weird. Suggestions?

Chris Povirk

unread,
Jun 19, 2012, 5:19:27 PM6/19/12
to Emily Soldal, Christian Edward Gruber, Louis Wasserman, guava-...@googlegroups.com
I would elaborate to say that "transform" is doubly awkward for
FluentFuture. There's the view issue we already discussed, for one.
Then there's the fact that future.transform(function) is basically
backward; function.transform(future) would make more sense. We can
try things like future.transformedBy(function) or
future.transformedWith(function). In fact, I pushed for something
like this with FluentIterable, which has the same "problem," but I
lost. Awkward as the "transform" name can be, I'm basically at peace
with it, there and here.

Emily Soldal

unread,
Jun 25, 2012, 3:04:31 PM6/25/12
to guava-...@googlegroups.com
I've been tinkering with this CL for a little while between doing other things, trying to get the API just right and I realised something;
Most of the functions in FLF must allow for specifying an executor, but specifying an executor at every step makes the API difficult to use, and adding convenience methods means that you double the number of methods, this will just lead to confusion in the end.

My proposed alternative is to allow for something like the following:

import static c.g.c.util.concurrent.FluentListenableFuture.*;

FluentListenableFuture<Thing> from(myFuture).transform(thingFunction).using(someExecutor).addCallback(asyncCallback).addCallback(anotherAsyncCallback);

In this example, #using(Executor) will return a FluentListenableFuture which will use the previously provided executor wherever applicable. I am thinking of adding a #inSameThread() method which reverts the assignment of the executor for subsequent calls. I think this will make it a little easier to use since there won't be such a vast number of similar methods.

Any thoughts?

- Emily
Reply all
Reply to author
Forward
0 new messages