A Challenge Problem for Promise Designers

Mark Miller erights at gmail.com
Sat Apr 27 17:50:19 PDT 2013


On Sat, Apr 27, 2013 at 3:49 PM, Tab Atkins Jr. <jackalmage at gmail.com>wrote:

> On Sat, Apr 27, 2013 at 2:21 PM, Dean Landolt <dean at deanlandolt.com>
> wrote:
> > On Fri, Apr 26, 2013 at 11:18 AM, Andreas Rossberg <rossberg at google.com>
> > wrote:
> >> On 26 April 2013 16:25, Dean Landolt <dean at deanlandolt.com> wrote:
> >> > The fundamental controversy, as Juan just noted, is how to precisely
> >> > identify a promise in order to do either of these two things. This
> >> > problem
> >> > isn't quite so clean cut, but it's much more important to solve. I've
> >> > been
> >> > trying to bring some attention to it over the last few days -- I hope
> >> > it's
> >> > clear that a `then` method is not enough to identify a promise
> language
> >> > construct -- this will subtly break existing code (e.g. casperjs).
> >>
> >> Let me note that this is not the fundamental controversy (not for me,
> >> anyway). The fundamental controversy is whether there should be any
> >> irregularity at all, as is unavoidably introduced by implicit
> >> flattening. The problem you describe just makes the negative effect of
> >> that irregularity worse.
> >
> > It may be a little late (I'm just catching up on these promise
> megathreads)
> > but I was suggesting that the irregularity posed by flattening is only a
> > distraction. AFAICT you're concern with flattening is actually in regard
> to
> > resolution semantics, right? Otherwise it's unobservable whether you
> have a
> > Promise<value> or a Promise<Promise<value>>. I'm trying to argue that
> given
> > a reliable branding a one-step resolver is easy and sensible to define
> (no
> > flattening), and a recursive resolver is an obvious extension. Almost
> > everyone would use the latter, but I completely agree that the former is
> > necessary too. No irregularities, everybody wins.
>
> Given the history of this issue so far, and the persistent
> miscommunications, I'd like to make sure that you understand what is
> meant by *non*-recursive flattening, which is what we on the monad
> side are arguing for.
>
> In a world with non-recursive flattening, like I want, this code:
>
> getAPromise()
>   .then(function(x) {
>     return 5;
>   }).then(function(y) {
>     alert(y);
>   });
>
> and this code:
>
> getAPromise()
>   .then(function(x) {
>     return Promise.accept(5);
>   }).then(function(y) {
>     alert(y);
>   });
>
> will both alert "5", not "<object Promise>".
>
> The only way to get it to alert "<object Promise>" is with code like this:
>
> getAPromise()
>   .then(function(x) {
>     return Promise.accept(Promise.accept(5));
>   }).then(function(y) {
>     alert(y);
>   });
>
> That is, you have to very explicitly double up on Promises.  It
> doesn't happen by accident.
>
> It's only this last case, which should be rare unless you're doing it
> on purpose, which we're all arguing about.  The recursive-flatten
> people want this case (and all higher-stacked cases, like "return
> Promise.accept(Promise.accept(Promise.accept(5)));") to all alert "5".
>
> This breaks some useful invariants, though.  It means that Promises
> are no longer monads, which prevents you from using monad libraries.
> It also means that you have to hack around the behavior in other cases
> - if you omit a callback from .then(), it's supposed to just "pass
> through" for that case, so the next .then() call to provide the
> callback gets the exact same value as it would if the callback were
> moved up.  This doesn't work with recursive-flattening, though - if
> you make a nested Promise explicitly, and then call .then(cb) on it,
> the callback will get a promise as an argument, but if you call
> .then().then(cb), the promise will have been flattened out.  You have
> to insert a special hack into the resolution mechanics to make this
> not happen.
>
> Since nested promises are hard to create unless you're doing it on
> purpose, can be useful, and produce more consistent semantics overall,
> we should be using non-recursive flattening. The only place where you
> want recursive flattening is when you're *assimilating an
> outside-world promise* from a foreign library, which should require an
> explicit action (so you don't end up "flattening" something like a
> Casper.js value, and getting nonsense out as a result).  We can just
> follow Promises/A+'s flattening semantics, but invoke them from some
> explicit function.  Best of all worlds.
>
> > It's been a few years but I recall an exchange we had where he took the
> > position that there shouldn't even be a method to test whether a value
> is a
> > promise -- IIRC he was arguing that any `value | Promise<value>`
> > functionality was unnecessary, and even hazardous. I was never clear on
> > exactly how this could be made to work, especially in interoperable
> > libraries, but as a language construct I suppose it's feasible. I'm
> curious
> > to hear where Dave stands now -- he eventually built support for
> thenables
> > into task.js (which I think was what sparked this exchange) but that
> could
> > have been out of convenience. Of course, with this approach I can't
> imagine
> > how promises could possibly be made nestable with one-step resolution
> (what
> > people seem to be calling "monadic" now?).
>
> This is the position that E takes,


I'm not sure which piece "this" refers to, but in E it is possible to test
whether a value is an unresolved promise. Testing this is discouraged, but
is sometimes necessary for various meta-programming tasks, like
serialization. It is not possible to test whether a value is a fulfilled
promise, since a fulfilled promise really is indistinguishable from its
fulfillment value.



> but it has special language support
> for promises, and does the unwrapping by itself, automatically.
> That's fine, and it produces a non-monadic form of promises.  JS
> likely can't do that, though - it's stuck with promises as "real"
> things, distinct from the values they wrap, so it should make the best
> of it and make them monadic.
>
> (If you don't understand the term "monadic", look at my earlier post
> in this thread, where I gave a short primer.  If you're still having
> trouble, let me know privately, and I'd be glad to explain it in more
> detail.)
>
> ~TJ
>



-- 
Text by me above is hereby placed in the public domain

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


More information about the es-discuss mailing list