code: @Override
      public <R> Future<R> flatMap(ThrowableFunction1<T, Future<R>> function) {
          Validator.requireNonNull(function, "Null is not a valid function");
          // Create new future expected to hold the value of the mapped type
          FutureImpl<R> future = new FutureImpl<>();
  
          // install success handler that will map the result before applying it
          onSuccess(value -> {
              // use the provided function to create a mapped future
              //it might actually fail due to the provided function throws an exception, hence we wrap it with a Try
              Try<Future<R>> mapped = Try(() -> function.apply(value));
              //add a recover function to the Try that fails this future with the error, else we complete this Future with the mapped Future
              mapped.recover(t -> Future.failed(t)).forEach(f -> f.onComplete(v -> future.complete(v)));
          });
  
          // install failure handler that just passes the failure/result through
          onFailure(t -> future.failure(t));
  
          return future;
      }
docs: /*
  (non-Javadoc)
  
  @see javascalautils.concurrent.Future#flatMap(java.util.function.Function)