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

Mark S. Miller erights at google.com
Thu Apr 25 18:49:03 PDT 2013


What is the semantics of Future.resolve?




On Thu, Apr 25, 2013 at 6:45 PM, Tab Atkins Jr. <jackalmage at gmail.com>wrote:

> On Thu, Apr 25, 2013 at 8:57 AM, Mark Miller <erights at gmail.com> wrote:
> > The refactoring of putting the "Q(srcP).then" in the deposit method
> > unburdened all clients such as the buy method above from doing this
> > postponement themselves. The new buy method on page 13 now reads:
> >
> >     buy: (desc, paymentP) => {
> >       // do whatever with desc, look up $10 price
> >       return (myPurse ! deposit(10, paymentP)).then(_ => good);
> >     }
> >
> > The old deposit method returned undefined or threw. The new deposit
> method
> > itself returns a promise-for-undefined that either fulfills to undefined
> or
> > rejects. However, in both cases, the promise for what the deposit method
> > will return remains the same, and so the buy method above did not become
> > burdened with having to do a doubly nested then in order to find out
> whether
> > the deposit succeeded. In addition, our first example line of client code
> >
> >     var ackP = paymentP ! deposit(10, myPurse);
> >
> > did not have to change at all. The Q(srcP).then at the beginning of the
> > deposit method will turn a purse into a promise for a purse, but will not
> > turn a promise for a purse into a promise for a promise for a purse. The
> > ackP remains a one-level promise whose fulfillment or rejection indicates
> > whether the deposit succeeds or fails.
> >
> > Call this refactoring "shifting the burden of postponement".
> >
> > I hope this gives some sense about why those who've experienced such
> > patterns like them. And I hope this provides a concrete and meaningful
> > challenge to those who think promises should work otherwise.
>
> This same thing is handled by Future.resolve(), no?  If you expect
> your function to receive either a value or a Future<value>, you can
> just pass it through Future.resolve() to get a guaranteed
> Future<value>.  It looks like it would result in roughly identical
> code to your refactoring - rather than this (taken from your first
> code example):
>
>     deposit: (amount, srcP) =>
>       Q(srcP).then(src => {
>         Nat(balance + amount);
>         m.get(src)(Nat(amount));
>         balance += amount;
>       })
>
> You'd just do this:
>
>     deposit: (amount, srcP) =>
>       Future.resolve(srcP).then(src => {
>         Nat(balance + amount);
>         m.get(src)(Nat(amount));
>         balance += amount;
>       })
>
> Right?
>
> Based on this example, it looks like the problem you're solving with
> recursive-unwrapping is that you speculatively wrap values in a
> promise, then rely on .then() to double-unwrap if necessary.  If this
> is an accurate summary of the problem, then Future.resolve() solves it
> better - same code, but better theoretical semantics.
>
> ~TJ
>



-- 
    Cheers,
    --MarkM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130425/e970b8dd/attachment.html>


More information about the es-discuss mailing list