A Challenge Problem for Promise Designers (was: Re: Futures)

Ron Buckton rbuckton at chronicles.org
Thu Apr 25 21:59:52 PDT 2013

I’m not sure I fully grok the use cases for FutureResolver#accept and having  Future<Future<value>>. Having to call an Unwrap extension method on a Task<Task<T>> in .NET is an unfortunate necessity. Also, since Future#then implicitly resolves a future it is difficult to return a Future<Future<value>> from a then.

In every case where I've used something like a Future it has always seemed more convenient to have it implicitly unwrap.

For native Futures, I don’t think it makes sense to try and unwrap just any object with a callable “then”. Its a necessity today for Promise libraries in ES5 as there’s no ideal way to brand an object as a Future.

This is what seems to make sense to me from a practical standpoint when using native Futures:

  *   If you resolve a Future (A) with a Future (B), the result of Future (A) should be B.
  *   This implicit unwrap should only work out of the box for Future subclasses or branded Futures.
  *   To coerce a “thenable” should be an explicit opt-in (e.g. Q(), or Future.of).
  *   There should be a well-defined mechanism for chaining futures from subclasses to preserve capabilities (ProgressFuture, etc.). One option might be a FutureFactory, another is to have subclasses override the .then method.
  *   An alternative to FutureResolver#accept that would allow for an explicit Future for a Future, might be to box the future, either explicitly (e.g. resolver.resolve({ future: f })) or with something like a Future.box() that encapsulates the future. In this way, if you need a future for a future you can support it on both FutureResolver and “then”.

A Future for a Future seems like a corner case compared to the broader simplicity of an implicit unwrap.

If we had Future.box() instead of FutureResolver#accept, we might be able to do things like:

function someFutureFutureV() {
  return new Future(function (resolver) {
    var F = someFutureV();
    var Fboxed = Future.box(F); // some special instance with a .value property?
    // F === Fboxed.value;
    resolver.resolve(Fboxed); // i.e. resolver.resolve(Future.box(F)) instead of resolver.accept(F)

someFutureFutureV().then(function (F) {
  // “then” unboxes Fboxed, just as it might have unwrapped F were it not boxed.
  // ...
  return Future.box(F); // another Fboxed
}).then(function (F) {
  // F is again preserved, this time from a call to then
  // ...
  return F; // no boxing this time
}).then(function (V) {
  // F is now unwrapped to V

While slightly more complicated for the FutureFuture case, the expectations are simpler for the broader usage scenarios, and the API surface is simpler (no FutureResolver#accept) for the most common use cases. If you really do intend to have a FutureFuture, Future.box would let you have a single way to opt in for both FutureResolver#resolve as well as Future#then.


Sent from Windows Mail

From: Tab Atkins Jr.
Sent: ‎Thursday‎, ‎April‎ ‎25‎, ‎2013 ‎8‎:‎38‎ ‎PM
To: Mark S. Miller
Cc: Mark Miller, es-discuss

On Thu, Apr 25, 2013 at 6:49 PM, Mark S. Miller <erights at google.com> wrote:
> What is the semantics of Future.resolve?

Creates an already-accepted future using the "resolve" algorithm,
which is the same magic that happens to the return value of a .then()
callback (if it's a future, it adopts the state; otherwise, it accepts
with the value).

In other words, "If this is a future, use it; otherwise, make me a
future for it".

es-discuss mailing list
es-discuss at mozilla.org

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130426/144b719b/attachment.html>

More information about the es-discuss mailing list