<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Aug 20, 2013 at 9:18 AM, Mark S. Miller <span dir="ltr"><<a href="mailto:erights@google.com" target="_blank">erights@google.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="im">On Tue, Aug 20, 2013 at 8:32 AM, Tab Atkins Jr. <span dir="ltr"><<a href="mailto:jackalmage@gmail.com" target="_blank">jackalmage@gmail.com</a>></span> wrote:<br>
</div><div class="gmail_extra"><div class="gmail_quote"><div class="im">
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div>On Tue, Aug 20, 2013 at 7:08 AM, Mark S. Miller <<a href="mailto:erights@google.com" target="_blank">erights@google.com</a>> wrote:<br>


> Hi Anne, Thanks for the reminder. My message of last night fell into that<br>
> same old trap (ignoring the storage cost) and that previous reversal of mine<br>
> is still mostly correct, However, the missing operation is not .fulfill for<br>
> the reasons Domenic correctly explains. It is .accept (possibly named .of)<br>
> because it observably differs from .resolve only to .flatMap observers;<br>
> whereas the distinction between "pending", "fulfilled" and "rejected" is<br>
> observable to .then observers.<br>
<br>
</div>I have no idea what happened in this thread, because people keep<br>
referring to "the earlier X" where by "earlier" they mean "in another<br>
unnamed thread, days/weeks ago" rather than just enumerating what<br>
they're talking about.  (This kind of thing is acceptable while the<br>
other threads are ongoing in parallel; it's not when the threads have<br>
been paged out of people's heads.)<br>
<br>
But in this paragraph, specifically, what are you talking about, Mark?<br></blockquote><div><br></div></div><div>See <<a href="http://lists.w3.org/Archives/Public/www-dom/2013AprJun/0213.html" target="_blank">http://lists.w3.org/Archives/Public/www-dom/2013AprJun/0213.html</a>>, which is the message Anne links to in the message I'm immediately replying to.</div>

<div><br></div><div>But yes, I agree that we've all been using terms like "earlier" too loosely, where we should be more explicit about context.</div><div class="im"><div><br></div><div><br></div><div> </div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

 What is this "missing operation",</blockquote><div><br></div></div><div>.accept</div><div class="im"><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

 who needs it, and why?</blockquote><div><br></div></div><div>To answer this precisely, we need good terminology to distinguish two levels of abstraction: The distinctions observable to the AP2.flatMap programmer and the coarser distinctions observable to the AP2.then programmer. Let's start ignoring thenables and considering only promises-vs-non-promises. Let's also start by ignoring rejection.</div>

<div><br></div><div>At the AP2.flatMap level, </div><div>  * for a promise p and an arbitrary value v, p may accept v. p is then in the "accepted" state.</div><div>  * for a promise p and a promise q, p may adopt q. p is then in the "adopting" state.</div>

<div>Putting these together, we can also say</div><div>  * for a promise p and an arbitrary value v, p is resolved to v if p either accepts v or adopts v. p is then in the "resolved" state.</div><div><br></div>
<div>
p2 = p1.flatMap(v1 => q2)</div><div><br></div><div>means, if p1 is accepted, then v1 will be what it has accepted.</div><div><br></div><div>If q2 is a promise, then p2 adopts q2. </div><div><br></div><div>p2.flatMap(...) fires as a result of acceptance but not adoption. If q2 accepts, then p2 likewise accepts and p2.flatMap fires by virtue of this acceptance.</div>

<div><br></div><div>At the P2.then level</div></div></div></div></blockquote><div><br></div><div><br></div><div>Should be "At the AP2.then level"</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>  * for a promise p and a non-promise v, p may be fulfilled with v. p is then in the fulfulled state.</div><div>  * for a promise p and a promise q, p may follow q. p is then in the following state.</div>

<div>  * Until a promise p is either fulfilled or rejected, it is pending.</div><div>Putting these together, we can also say</div><div>  * for a promise p and an arbitrary value v, p is resolved to v if either p is fulfilled with v or p follows v. p is then in the "resolved" state.</div>

<div><br></div><div>p4 = p3.then(v3 => v4)</div><div><br></div><div>means, if p3 is fulfilled, then v3 will be what p3 is fulfilled with.</div><div><br></div><div>p4 is resolved to v4. If v4 is a promise, then p4 follows v4. Else p4 is fulfilled with v4. </div>

<div><br></div><div>p4.then fires as a result of fulfillment but not following. If p4 follows v4 and v4 fulfills, then p4 likewise fulfills and p4.then fires by virtue of this fulfillment.</div><div><br></div><div>Notice that "resolved" is the same states at each level, even though these states are described differently. That is why we can use the same term at both levels. Likewise, the concept of "unresolved" is meaningful at both levels.</div>
<div class="im">
<div><br></div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
>From what I understood talking to Domenic, here's what we needed:<br>
<br>
1. Promise.resolve() and Promise.reject().  These just take a value<br>
and wrap it in a Promise, putting it on the success or failure track.<br></blockquote><div><br></div></div><div>I'm totally confused by your description of reject, but let's leave it aside for now as I have above.</div>

<div><br></div><div>I'm not so much concerned with the static .resolve method, since the extra storage cost for the static method is negligible. However, what does aResolve.resolve do? If it causes its promise to accept, this must be observably different to .flatMap observers than if it causes its promise to adopt. This difference is not observable to .then observers, which is why I've accidentally missed this issue twice now. But since an implementation cannot know ahead of time whether there might be .flatMap observers, using .accept for .resolve would impose prohibitive storage costs on .then oriented patterns. See the message Anne linked to.</div>
<div class="im">
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
2. Promise#then() and Promise#flatMap().  flatMap waits for pending<br>
promises to become resolved or rejected,</blockquote><div><br></div></div><div>If p adopts q and q is unresolved, then p is resolved but p.flatMap does not fire.</div><div class="im"><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

 and calls its callbacks<br>
accordingly; then() waits for pending or resolved promises to become<br>
fulfilled or rejected, and calls its callbacks accordingly.<br>
<br>
3. The resolved value of a promise (what's passed to the success<br>
callback of flatMap()) is simply the value in the promise.</blockquote><div><br></div></div><div>True for acceptance, not for adoption.</div><div class="im"><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

  The<br>
fulfilled value of a promise (what's passed to the success callback of<br>
then()) depends on what's inside the promise: if it's a plain value,<br>
that's the fulfilled value; if it's a promise, its that promise's<br>
fulfilled value.<br>
<br>
Do you think we need anything else?  If so, why, and for what purpose?<br></blockquote><div><br></div></div><div>Only to avoid the prohibitive storage cost of using .accept to do the job of .resolve. Storage aside, there is no semantic need to distinguish these two.</div>
<div class="im">
<div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
(Note that if anyone thinks we need something that eagerly flattens a<br>
promise, rather than flattening happening implicitly via the<br>
definition of "fulfilled value" for then(), realize that this eager<br>
flattening operation is hostile to lazy promises.  While this might be<br>
*useful* in some cases, it's probably not something we need or want in<br>
the core language, or if we do, it should be given an appropriately<br>
descriptive name, rather than yet another synonym for "accept".)<br></blockquote><div><br></div></div><div>I agree that we do not need eager flattening.</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">


<span><font color="#888888"><br>
~TJ<span class="HOEnZb"><font color="#888888"><br>
</font></span></font></span></blockquote></div><span class="HOEnZb"><font color="#888888"><br><br clear="all"><div><br></div>-- <br>    Cheers,<br>    --MarkM
</font></span></div></div>
</blockquote></div><br><br clear="all"><div><br></div>-- <br>    Cheers,<br>    --MarkM
</div></div>