> -----Original Message-----
> From: Tab Atkins Jr. [mailto:[email protected]]
> Sent: Monday, April 29, 2013 11:21 AM
> To: Ron Buckton
> Cc: Mark Miller; David Sheets; Mark S. Miller; es-discuss; public-script-
> [email protected]; David Bruant; Dean Tribble
> Subject: Re: A Challenge Problem for Promise Designers
>
> On Mon, Apr 29, 2013 at 11:03 AM, Ron Buckton <[email protected]>
> wrote:
> > Thanks for the clarifications re: Future as a monad. My understanding of
> this is as follows (please correct me if I am wrong):
> >
> > * The expected result of the resolve/reject callbacks passed to
> Future#then is itself a Future.
> > * If the result of the resolve/reject callbacks is not a Future it is
> > logically
> lifted into a Future, by accepting the value on the Future that is the result
> of
> Future#then.
> > * The Future result of the callback is merged into the Future returned
> Future#then then by chaining to either Future#then (Future#done?) of the
> callback result.
> > * Given this, it is not usually necessary to "recursively unwrap" or
> > "flatten"
> a Future. As a result Future#then should not flatten the result. This would
> preserve Future.accept(Future.accept(value)).then().then(F => /* F is
> Future(value) */).
>
> All correct. (Some of your precise mechanical details are probably wrong, but
> you got all the important bits.)
I updated [1] my rough implementation of Future based on this discussion. This
has the following changes from the previous [2] version which was based on the
DOM spec for Future:
* The resolver's resolve algorithm tests value to determine if it is a Future
instance (rather than a "thenable"). This could later be done by checking
branding or by checking for a symbol.
* The resolver's resolve algorithm only unwraps the value once if it is a
Future, rather than performing flattening. It does this by calling the
resolver's accept algorithm in the "resolve" future callback for rather than
the resolve algorithm.
* In the steps for Future#then, if the "resolveCallback" is null, the "resolve"
callback becomes a future callback for resolver and its accept algorithm. This
is to preserve the value for something like:
Future.accept(Future.accept(value)).then().then(F => /* F is Future(value)
*/)
Future.accept(Future.accept(Future.accept(value))).then().then(FF => /* FF
is Future(Future(value)) */)
* In the steps for some/any/every, the future callbacks that are created that
used the resolver's resolve algorithm now use the resolver's accept algorithm.
This is to preserve the value for something like:
Future.any(Future.accept(Future.accept(value))).then(F => /* F is
Future(value) */)
Future.any(Future.accept(Future.accept(Future.accept(value)))).then(FF =>
/* FF is Future(Future(value)) */)
* Added Future.from to perform explicit assimilation (with only one level of
unwrap, as with Future#then)
* Added Future.isFuture to test for native Futures
Hopefully I've captured the mechanical details correctly in the implementation.
[1, updated implementation]
https://github.com/rbuckton/promisejs/blob/master/Future1/Future.ts
[2, spec implementation]
https://github.com/rbuckton/promisejs/blob/master/Future0/Future.ts
Ron
>
> > I can also agree that it is inherently unsafe to assimilate "thenables" for
> Future.resolve/FutureResolver#resolve, due to possible collisions with the
> property name on existing objects such as with casper.js. This kind of
> collision
> is the same rationale for having an @iterator symbol for iterators, though I
> wouldn't think the same resolution is likely the best result in this case. I
> am of
> the opinion that native Futures should only resolve native Futures (or
> possibly their subclasses). To assimilate you could have a Future.of (or
> possibly Future.from to match Array.from for "array-like" objects), which
> would assimilate "future-like" objects (i.e. "thenables"), but only via one
> level of unwrapping and not recursively.
>
> I'm fine with the concept of using branding (via a symbol) to denote that
> something should be treated like a future. I'm also fine with only allowing
> Promises and subclasses. Whatever people decide is better.
>
> Domenic, after a lot of experience, thinks that the assimilation procedure
> should be recursive (presumably "bottoming out" when it hits a native
> promise). I'm fine with that. It does mean that if you need to assimilate a
> thenable for a Casper object, it'll do the wrong thing, but that's the price
> you
> pay for arbitrary library compat. If you know your foreign thenable is only a
> single layer, you can safeguard its contents yourself, by chaining .then() and
> returning a native Promise holding the value. Then, the assimilation
> procedure will "eat" the thenable, hit the Promise and adopt its state, and
> the Casper object (or whatever) will be safe.
>
> > I'm still concerned about cancellation, but will spin up another thread to
> hopefully spark some thoughtful discussion on the topic.
>
> Go for it. I have given some thought to it, and think I have a reasonable
> model.
>
> ~TJ
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss