Object-Functional Concurrent Programming with Javaslang

Scala 2.12 will include Future improvements as Viktor Klang described on his Github-Blog "Letters from Klang".

Javaslang's Future can also benefit from these ideas. But there came another improvement to my mind that will reduce some of the ceremony when working with Promises.

Internalizing Promise creation

We follow Scala's design, Future represents an asynchronous computation result. It can be only read. When different Futures (read: asynchronous computations) depend on each other, we may need to write a result to a Future. We use a Promise for that purpose.

Like Scala, we currently do that in an imperative way, which is a little bit awkward:

<T, U> Future<U> myComputation(Future<T> future) {
    Promise<T> promise = Promise.make();
    future.onComplete(result -> {
        ...
        promise.complete(...);
    });
    return promise.future();
}

The Promise creation can be internalized, we will add the following syntactic sugar:

<T, U> Future<U> myComputation(Future<T> future) {
    return Future.of(promise ->
        future.onComplete(result -> {
            ...
            promise.complete(...);
        })
    );
}

Making Promise a Function

By making Promise a Function we can benefit from composition for example:

class Promise<T> implements Function1<Try<T>, Boolean> {
    @Override
    public Boolean apply(Try<T> result) {
        return tryComplete(result);
    }
    ...
}

This is our current Future.map() implementation:

<U> Future<U> map(Function<? super T, ? extends U> mapper) {
    return transformValue(t -> t.map(mapper::apply));
}

<U> Future<U> transformValue(
        Function<? super Try<T>, ? extends Try<? extends U>> f) {
    final Promise<U> promise = Promise.make(executorService());
    onComplete(t -> Try.run(() -> promise.complete(f.apply(t)))
                       .onFailure(promise::failure));
    return promise.future();
}

Having a Promise that is a Function, the map() method will start looking beautiful:

<U> Future<U> map(Function<? super T, ? extends U> mapper) {
    return Future.of(p -> onComplete(p.compose(mapper)));
}

Note: Scala developers might also be interested in these additions. Scala's Future.map() method could look like this: Future(onComplete(_ compose mapper))

Concurrent Tree creation

The above looks theoretic. I want to give an example how Future and Promise could be used to concurrently build a persistent/immutable Tree structure.

Javaslang 2.1.0 will contain better integration of Future and Promise. In particular Tree will have a function that concurrently builds trees:

static <T> Future<Node<T>> of(T seed,
        Function<? super T, Future<? extends Iterable<? extends T>>>
        descend) {
    return Future.of(promise -> descend.apply(seed)
        .onComplete(result -> result
            .onSuccess(children -> promise.completeWith(
                Future.sequence(
                    Iterator.ofAll(children).map(child ->
                        Tree.of(child, descend)
                    )
                ).map(childNodes -> Tree.of(seed, childNodes)))
            )
            .onFailure(promise::failure)
        )
    );
}

Given that we are able to build a Tree concurrently like this:

Tree.of(rootValue, value -> asyncGetChildren(value))

Example:

import static javaslang.API.*;
import javaslang.collection.*;
import javaslang.concurrent.Future;

public class Test {

    public static void main(String[] args) {
        Tree.of(new Aggregate(1),
                aggr -> getAggregates(aggr.getChildrenIds()))
            .onComplete(result -> {
                result.onSuccess(tree -> println(tree.draw()));
                Future.DEFAULT_EXECUTOR_SERVICE.shutdown();
            });
    }

    static Future<Seq<Aggregate>> getAggregates(Seq<Integer> ids) {
        // dummy, real impl may call remote services
        return Future.successful(ids.map(Aggregate::new));
    }

    static class Aggregate {

        private int id;

        Aggregate(int id) {
            this.id = id;
        }

        // also a dummy impl, for the sake of this example
        List<Integer> getChildrenIds() {
            return (id >= 1000)
                   ? List.empty()
                   : List.range(0, 2).map(i -> id * 10 + i);
        }

        @Override
        public String toString() {
            return "" + id;
        }
    }
}

This is the output:

1
├──10
│  ├──100
│  │  ├──1000
│  │  └──1001
│  └──101
│     ├──1010
│     └──1011
└──11
   ├──110
   │  ├──1100
   │  └──1101
   └──111
      ├──1110
      └──1111

Like most other types, Javaslang's Tree is a Value, which can be converted to all other Javaslang Values (and also to Java collections etc). So let's finally convert the async Tree to a List:

Future<Tree<Aggregate>> asyncTree =
    Tree.of(rootValue, value -> asyncGetChildren(value));

// Some(javaslang.collection.List) or None, if an async error occurs
Option<List<Aggregate>> listOption =
    asyncTree.toOption().map(Tree::toList);

Please note that it is also possible to convert Javaslang types to Java types:

// this is a java.util.List
Optional<List<Aggregate>> listOption =
    asyncTree.toJavaOptional().map(Tree::toJavaList);

Have fun!

- Daniel