W3C home > Mailing lists > Public > public-script-coord@w3.org > April to June 2013

Re: Promises: Auto-assimilating thenables returned by .then() callbacks: yay/nay?

From: Mark S. Miller <erights@google.com>
Date: Mon, 6 May 2013 13:29:02 -0700
Message-ID: <CABHxS9jSEeOb8tZ5k=7t=sM-KMO4KSa4_QgCHip31Ad67UKCGQ@mail.gmail.com>
To: "Tab Atkins Jr." <jackalmage@gmail.com>
Cc: Jonas Sicking <jonas@sicking.cc>, Sam Tobin-Hochstadt <samth@ccs.neu.edu>, Domenic Denicola <domenic@domenicdenicola.com>, "public-script-coord@w3.org" <public-script-coord@w3.org>
Yes to both. My point indeed as that these are two use cases that do
support the possibility of promises-for-promises. I will explain separately
why I don't find these these two compelling, and why the second example
cuts both ways.


On Mon, May 6, 2013 at 12:28 PM, Tab Atkins Jr. <jackalmage@gmail.com>wrote:

> On Mon, May 6, 2013 at 11:19 AM, Mark S. Miller <erights@google.com>
> wrote:
> > On Mon, May 6, 2013 at 10:57 AM, Tab Atkins Jr. <jackalmage@gmail.com>
> > wrote:
> >> On Mon, May 6, 2013 at 10:39 AM, Mark S. Miller <erights@google.com>
> >> wrote:
> >> > I'm surprised that no one has come up with *any* use cases. As I
> >> > mentioned
> >> > before, I have encountered some use cases that individually seem to
> >> > argue
> >> > for promises-for-promises. But I don't find them compelling. Given the
> >> > absence of promises-for-promises, these can easily work around their
> >> > absence. Here are two use cases. One of them even cuts both ways.
> >> >
> >> > * The generic contract host defined in Figure 3 of
> >> > <http://research.google.com/pubs/pub40673.html> requires its contract
> >> > function to be a function of resolved arguments. It cannot handle a
> >> > contract
> >> > function that could validly take a pending promise as argument because
> >> > it
> >> > uses a Q.all to determine when all the arguments have arrived.
> >>
> >> In this case, you mean that the contract function could take a
> >> fulfilled promise for a pending promise, but it couldn't do so it
> >> promises were auto-flattened (so that it was just a pending promise)?
> >
> >
> > No. The problem is created merely by defining and trying to use a
> contract
> > function that takes a pending promise as argument. Promise parameters
> aside,
> > if a contract function takes a parameter x, the Q.all within
> > makeContractHost will be .then-ing a promise-for-x. If
> promises-for-promises
> > were possible, then x could be a pending promise and the Q.all would be
> > .then-ing a promise-for-a-pending promise. When this outer promise
> becomes a
> > fulfilled-promise-for-a-pending-promise, the Q.all would fire providing
> the
> > contract function the outer promise's fulfillment value, which is the
> > pending promise. Given that promises-for-promises are not possible, the
> only
> > working contract functions that can be provided to makeContractHost are
> > those whose arguments are anything other than pending promises.
>
> Right; apologies for the confusion, this is what I meant.
>
> *Given* nestable promises, the contract function *can* take promise
> arguments, because the caller can produce a promise for it.  So this
> is a gain in functionality.
>
> This is actually simply another example of the "distinct types of
> promises" meta-use-case - the "contract host" returned by
> makeContractHost runs on promises-for-an-argument, which the contract
> users fulfill at their leisure.  The contract function itself can take
> a promise-for-[anything], which is completely distinct.
>
> This is a nice, completely different example of distinct promises
> being useful when nested.
>
> >> > * The Infinite Queue at
> >> >
> >> > <
> http://wiki.ecmascript.org/doku.php?id=strawman:concurrency#infinite_queue
> >
> >> > cuts both ways. If the producer enqueues a pending promise, the
> consumer
> >> > cannot detect this as different from the producer not yet having
> >> > enqueued
> >> > anything. For most purposes, this is the more convenient behavior.
> >> > However,
> >> > for flow control purposes, the consumer might want to limit how far
> >> > ahead of
> >> > the producer it dequeues, and this ambiguity would cause the consumer
> to
> >> > stall inappropriately.
> >>
> >> I believe this relies on auto-flattening, no?  "front ! head" returns
> >> a promise for front.head, which is assumed to be a plain value.  If
> >> you enqueue a promise, assuming monadic flattening, I think you should
> >> just get the promise back out.  (However, I'm not entirely clear on
> >> the semantics of !.)
> >
> > "p ! foo" is just syntactic sugar for "Q(p).get('foo')". In the absence
> of
> > extended or remote promises, this is essentially equivalent to
> >
> > Q(p).then(v => v.foo)
>
> Well, "v=>Future.accept(v.foo)", given monadic resolution semantics.
> (If .then() unwraps fully, this is obviously unnecessary.)
>
> I believe my statement was correct, then - given monadic resolution
> semantics and the code as presented at that link, enqueuing a pending
> promise and then dequeueing will get you a fulfilled promise for a
> pending promise.  Auto-flattening gives you a simple pending promise.
>
> ~TJ
>



-- 
    Cheers,
    --MarkM
Received on Monday, 6 May 2013 20:29:30 UTC

This archive was generated by hypermail 2.3.1 : Tuesday, 6 January 2015 21:37:49 UTC