- From: Mark Miller <erights@gmail.com>
- Date: Sat, 27 Apr 2013 17:50:19 -0700
- To: "Tab Atkins Jr." <jackalmage@gmail.com>
- Cc: Dean Landolt <dean@deanlandolt.com>, Andreas Rossberg <rossberg@google.com>, "Mark S. Miller" <erights@google.com>, "public-script-coord@w3.org" <public-script-coord@w3.org>, Dean Tribble <tribble@e-dean.com>, es-discuss <es-discuss@mozilla.org>
- Message-ID: <CAK5yZYgU-iknmLs+zkN4WH+WTw8Hq1Dq38SqCBzveZEo+j_0Ag@mail.gmail.com>
On Sat, Apr 27, 2013 at 3:49 PM, Tab Atkins Jr. <jackalmage@gmail.com>wrote: > On Sat, Apr 27, 2013 at 2:21 PM, Dean Landolt <dean@deanlandolt.com> > wrote: > > On Fri, Apr 26, 2013 at 11:18 AM, Andreas Rossberg <rossberg@google.com> > > wrote: > >> On 26 April 2013 16:25, Dean Landolt <dean@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
Received on Sunday, 28 April 2013 00:50:46 UTC