Fixing `Promise.resolve()`

classic Classic list List threaded Threaded
17 messages Options
Reply | Threaded
Open this post in threaded view
|

Fixing `Promise.resolve()`

C. Scott Ananian
Hopefully everyone has had a little bit of time to think over the
issues with Promise.resolve().

Last week I proposed three different reasonable semantics for
`Promise.resolve`, none of which involve the `[[PromiseConstructor]]`
internal field:
https://esdiscuss.org/topic/subclassing-es6-objects-with-es5-syntax#content-50

I continue to feel that the "no species" proposal is the best
alternative, reasoning that `Promise.resolve` is more like an explicit
constructor than an species-using instance-transformation method.
Here's that proposal again:

> Promise.resolve(x)
> 1. Let C be the this value.
> 2. If IsPromise(x) is true,
>      a. Let constructor be the value of Get(x, "constructor").
>      b. ReturnIfAbrupt(constructor)
>      c. If SameValue(constructor, C) is true, return x.
> 3. Let promiseCapability be NewPromiseCapability(C).
> 4. ReturnIfAbrupt(promiseCapability).
> 5. Let resolveResult be Call(promiseCapability.[[Resolve]], undefined, «x»).
> 6. ReturnIfAbrupt(resolveResult).
> 7. Return promiseCapability.[[Promise]].

All mentions of [[PromiseConstructor]] should then be
garbage-collected from the spec.

This simplifies the semantics and fixes the "hidden new.target"
brokenness which affects interoperability with code written in ES5
syntax.  Eliminating "species" here also yields more useful behavior
from `P.resolve` if an subclass sets `P[Symbol.species] !== P`.

It's my understanding that Mark Miller volunteered to champion the
changes to `Promise.resolve` at the next TC39 meeting.  (Thanks,
Mark!).

I'll update `es6-shim` and `core-js`/`babel` if/when TC39 reaches
consensus on this.

Thanks!
 --scott
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Fixing `Promise.resolve()`

Allen Wirfs-Brock
At the May 27-29 TC39 meeting we agreed to make  this change.

Allen

On May 7, 2015, at 2:47 PM, C. Scott Ananian wrote:

> Hopefully everyone has had a little bit of time to think over the
> issues with Promise.resolve().
>
> Last week I proposed three different reasonable semantics for
> `Promise.resolve`, none of which involve the `[[PromiseConstructor]]`
> internal field:
> https://esdiscuss.org/topic/subclassing-es6-objects-with-es5-syntax#content-50
>
> I continue to feel that the "no species" proposal is the best
> alternative, reasoning that `Promise.resolve` is more like an explicit
> constructor than an species-using instance-transformation method.
> Here's that proposal again:
>
>> Promise.resolve(x)
>> 1. Let C be the this value.
>> 2. If IsPromise(x) is true,
>>    a. Let constructor be the value of Get(x, "constructor").
>>    b. ReturnIfAbrupt(constructor)
>>    c. If SameValue(constructor, C) is true, return x.
>> 3. Let promiseCapability be NewPromiseCapability(C).
>> 4. ReturnIfAbrupt(promiseCapability).
>> 5. Let resolveResult be Call(promiseCapability.[[Resolve]], undefined, «x»).
>> 6. ReturnIfAbrupt(resolveResult).
>> 7. Return promiseCapability.[[Promise]].
>
> All mentions of [[PromiseConstructor]] should then be
> garbage-collected from the spec.
>
> This simplifies the semantics and fixes the "hidden new.target"
> brokenness which affects interoperability with code written in ES5
> syntax.  Eliminating "species" here also yields more useful behavior
> from `P.resolve` if an subclass sets `P[Symbol.species] !== P`.
>
> It's my understanding that Mark Miller volunteered to champion the
> changes to `Promise.resolve` at the next TC39 meeting.  (Thanks,
> Mark!).
>
> I'll update `es6-shim` and `core-js`/`babel` if/when TC39 reaches
> consensus on this.
>
> Thanks!
> --scott
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
>

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Fixing `Promise.resolve()`

C. Scott Ananian
Thanks!  It looks like core-js has already patched in the new spec: https://github.com/zloirock/core-js/issues/75

I've opened https://github.com/paulmillr/es6-shim/issues/344 on es6-shim, and I'll see if I can get a patch together for it.


Allen: Will this be an errata to ES6, part of ES7, or "something else"?
  --scott

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Fixing `Promise.resolve()`

Mark S. Miller-2
Hi Scott,

If the change is as simple as it appears, it seems it will go into ES6 itself!

Thanks for pushing this forward.


On Tue, Jun 2, 2015 at 1:25 PM, C. Scott Ananian <[hidden email]> wrote:
Thanks!  It looks like core-js has already patched in the new spec: https://github.com/zloirock/core-js/issues/75

I've opened https://github.com/paulmillr/es6-shim/issues/344 on es6-shim, and I'll see if I can get a patch together for it.


Allen: Will this be an errata to ES6, part of ES7, or "something else"?
  --scott



--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Fixing `Promise.resolve()`

Allen Wirfs-Brock

On Jun 2, 2015, at 2:01 PM, Mark S. Miller wrote:

Hi Scott,

If the change is as simple as it appears, it seems it will go into ES6 itself!

The fix has already been made to the production copy that will be released in a couple weeks when we have ECMA GA approval

Allen




Thanks for pushing this forward.


On Tue, Jun 2, 2015 at 1:25 PM, C. Scott Ananian <[hidden email]> wrote:
Thanks!  It looks like core-js has already patched in the new spec: https://github.com/zloirock/core-js/issues/75

I've opened https://github.com/paulmillr/es6-shim/issues/344 on es6-shim, and I'll see if I can get a patch together for it.


Allen: Will this be an errata to ES6, part of ES7, or "something else"?
  --scott



--
    Cheers,
    --MarkM


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Fixing `Promise.resolve()`

Axel Rauschmayer
Is there any way to find out how this works *now*? I can’t find the May 2015 meeting notes, either.

Do all static Promise methods now just use `this` (e.g. `Promise.all()` → `this.promiseResolve(···)`)? Or only `Promise.resolve()`?

Thanks!

Axel


On 02 Jun 2015, at 23:28, Allen Wirfs-Brock <[hidden email]> wrote:


On Jun 2, 2015, at 2:01 PM, Mark S. Miller wrote:

Hi Scott,

If the change is as simple as it appears, it seems it will go into ES6 itself!

The fix has already been made to the production copy that will be released in a couple weeks when we have ECMA GA approval

Allen




Thanks for pushing this forward.


On Tue, Jun 2, 2015 at 1:25 PM, C. Scott Ananian <[hidden email]> wrote:
Thanks!  It looks like core-js has already patched in the new spec: https://github.com/zloirock/core-js/issues/75

I've opened https://github.com/paulmillr/es6-shim/issues/344 on es6-shim, and I'll see if I can get a patch together for it.


Allen: Will this be an errata to ES6, part of ES7, or "something else"?
  --scott



--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

-- 
Dr. Axel Rauschmayer
[hidden email]
rauschma.de




_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Fixing `Promise.resolve()`

Allen Wirfs-Brock
Revised definition of Promise.resolve:

25.4.4.5 Promise.resolve ( x )
The resolve function returns either a new promise resolved with the passed argument, or the argument itself if the argument is a promise produced by this constructor.

1. Let C be the this value.
2. If Type(C) is not Object, throw a TypeError exception.
3. If IsPromise(x) is true,
     a. Let xConstructor be Get(x, "constructor").
     b. ReturnIfAbrupt(xConstructor).
     c. If SameValue(xConstructor, C) is true, return x.
4. Let promiseCapability be NewPromiseCapability(C).
 5. ReturnIfAbrupt(promiseCapability).
6. Let resolveResult be Call(promiseCapability.[[Resolve]], undefined, «x»).
7. ReturnIfAbrupt(resolveResult).
8. Return promiseCapability.[[Promise]].

So far, no changes to any other Promise static methods

Allen





On Jun 9, 2015, at 10:19 PM, Axel Rauschmayer wrote:

Is there any way to find out how this works *now*? I can’t find the May 2015 meeting notes, either.

Do all static Promise methods now just use `this` (e.g. `Promise.all()` → `this.promiseResolve(···)`)? Or only `Promise.resolve()`?

Thanks!

Axel


On 02 Jun 2015, at 23:28, Allen Wirfs-Brock <[hidden email]> wrote:


On Jun 2, 2015, at 2:01 PM, Mark S. Miller wrote:

Hi Scott,

If the change is as simple as it appears, it seems it will go into ES6 itself!

The fix has already been made to the production copy that will be released in a couple weeks when we have ECMA GA approval

Allen




Thanks for pushing this forward.


On Tue, Jun 2, 2015 at 1:25 PM, C. Scott Ananian <[hidden email]> wrote:
Thanks!  It looks like core-js has already patched in the new spec: https://github.com/zloirock/core-js/issues/75

I've opened https://github.com/paulmillr/es6-shim/issues/344 on es6-shim, and I'll see if I can get a patch together for it.


Allen: Will this be an errata to ES6, part of ES7, or "something else"?
  --scott



--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

-- 
Dr. Axel Rauschmayer
[hidden email]
rauschma.de





_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

RE: Fixing `Promise.resolve()`

Domenic Denicola
Allen, that change seems wrong. I thought we were only changing the IsPromise steps. The actual construction should still go through species. If nothing else, it should do so for consistency with reject.

The motivation of @@species, as I understood it, was to allow alternate subclass constructor signatures (originally for Array and TypedArray, but Promise can benefit as well). It’s understandable to not involve @@species when doing weak type-tests. But any time you construct a promise instance, you should go through @@species, instead of the constructor directly.

Some example usages:

- Creating a LabeledPromise subclass (for better debugging, like RSVP's promises + Ember promise inspector) whose constructor signature is `new LabeledPromise(label, executor)`
- Creating a SaneArray subclass whose constructor signature is `new SaneArray(...elements)` without the special-case for a single argument.
- A more complicated usage in a proposed Element/HTMLElement/MyCustomElement hierarchy [1], to allow custom elements to have custom constructor signatures but still work well with various element-creating parts of the platform.

The LabeledPromise case will, as currently specified, work great. LabeledPromise has a custom `LabeledPromise[Symbol.species](executor)` which basically does `return new this("<derived promise>", executor)`. Then it doesn't have to override `.resolve`, `.reject`, `.all`, or `.then`. However, with your change, `.resolve` will no longer work correctly, even though `.reject` will.

However, the SaneArray case actually will only work for the instance methods, which use ArraySpeciesCreate. In contrast, Array.of and Array.from use Construct(C, <<len>>). That seems like a bug in the spec?

[1]: https://github.com/domenic/element-constructors/blob/cdfe5a1d865e25d265074418df7918fda959e403/element-constructors.js#L101-L107
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Fixing `Promise.resolve()`

Allen Wirfs-Brock

On Jun 10, 2015, at 8:22 AM, Domenic Denicola wrote:

Allen, that change seems wrong. I thought we were only changing the IsPromise steps. The actual construction should still go through species. If nothing else, it should do so for consistency with reject.

The motivation of @@species, as I understood it, was to allow alternate subclass constructor signatures (originally for Array and TypedArray, but Promise can benefit as well). It’s understandable to not involve @@species when doing weak type-tests. But any time you construct a promise instance, you should go through @@species, instead of the constructor directly.

Some example usages:

- Creating a LabeledPromise subclass (for better debugging, like RSVP's promises + Ember promise inspector) whose constructor signature is `new LabeledPromise(label, executor)`
- Creating a SaneArray subclass whose constructor signature is `new SaneArray(...elements)` without the special-case for a single argument.
- A more complicated usage in a proposed Element/HTMLElement/MyCustomElement hierarchy [1], to allow custom elements to have custom constructor signatures but still work well with various element-creating parts of the platform.

The LabeledPromise case will, as currently specified, work great. LabeledPromise has a custom `LabeledPromise[Symbol.species](executor)` which basically does `return new this("<derived promise>", executor)`. Then it doesn't have to override `.resolve`, `.reject`, `.all`, or `.then`. However, with your change, `.resolve` will no longer work correctly, even though `.reject` will.

However, the SaneArray case actually will only work for the instance methods, which use ArraySpeciesCreate. In contrast, Array.of and Array.from use Construct(C, <<len>>). That seems like a bug in the spec?

[1]: https://github.com/domenic/element-constructors/blob/cdfe5a1d865e25d265074418df7918fda959e403/element-constructors.js#L101-L107

I don't think we discussed the possibility of Promise subclasses with different promise signatures at the May meeting; we mainly focused on the expectation that SubPromise.resolve(x) should yield an instance of SubPromise.  But I see your logic, indirecting through species provides a way for subclasses to to change their constructor signature and still work correctly with the other inherited Promise static methods. 

Allen


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Fixing `Promise.resolve()`

C. Scott Ananian
In reply to this post by Domenic Denicola
@Domenic: please see the previous discussion at https://esdiscuss.org/topic/subclassing-es6-objects-with-es5-syntax#content-50 since there is much more discussion back-and-forth there.

And you are correct about Promise.reject; Allen is proposing to remove the @@species from that method as well.

The changes to `Promise.resolve` are needed to make other use cases work properly (see that other thread).  It seems that your particular use case could be better handled by overriding `LabelledPromise.resolve` to take an additional "label" argument.

Your understanding of @@species seems to be different from the use cases envisioned by the smalltalk concept named species, although it's an interesting idea in its own right.  You should probably call it something like "custom constructors", though, to differentiate it from the smalltalk "species", which is used in the smalltalk world to describe two related things (1) the "generic type" of the object, for type tests, and (2) the "derived type" which instance-transformation methods should yield.[*]  In smalltalk (as I understand it) custom constructors are not part of the design.
  --scott

[*] ""Answer the preferred class for reconstructing the receiver. For example,  collections create new collections whenever enumeration messages such as collect: or select: are invoked. The new kind of collection is determined by the species of the original collection. Species and class are not always the  same. For example, the species of Interval is Array." http://forum.world.st/species-td3374278.html

On Wed, Jun 10, 2015 at 11:22 AM, Domenic Denicola <[hidden email]> wrote:
Allen, that change seems wrong. I thought we were only changing the IsPromise steps. The actual construction should still go through species. If nothing else, it should do so for consistency with reject.

The motivation of @@species, as I understood it, was to allow alternate subclass constructor signatures (originally for Array and TypedArray, but Promise can benefit as well). It’s understandable to not involve @@species when doing weak type-tests. But any time you construct a promise instance, you should go through @@species, instead of the constructor directly.

Some example usages:

- Creating a LabeledPromise subclass (for better debugging, like RSVP's promises + Ember promise inspector) whose constructor signature is `new LabeledPromise(label, executor)`
- Creating a SaneArray subclass whose constructor signature is `new SaneArray(...elements)` without the special-case for a single argument.
- A more complicated usage in a proposed Element/HTMLElement/MyCustomElement hierarchy [1], to allow custom elements to have custom constructor signatures but still work well with various element-creating parts of the platform.

The LabeledPromise case will, as currently specified, work great. LabeledPromise has a custom `LabeledPromise[Symbol.species](executor)` which basically does `return new this("<derived promise>", executor)`. Then it doesn't have to override `.resolve`, `.reject`, `.all`, or `.then`. However, with your change, `.resolve` will no longer work correctly, even though `.reject` will.

However, the SaneArray case actually will only work for the instance methods, which use ArraySpeciesCreate. In contrast, Array.of and Array.from use Construct(C, <<len>>). That seems like a bug in the spec?

[1]: https://github.com/domenic/element-constructors/blob/cdfe5a1d865e25d265074418df7918fda959e403/element-constructors.js#L101-L107
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

RE: Fixing `Promise.resolve()`

Domenic Denicola
In reply to this post by Allen Wirfs-Brock
From: Allen Wirfs-Brock [mailto:[hidden email]]

> I don't think we discussed the possibility of Promise subclasses with different promise signatures at the May meeting; we mainly focused on the expectation that SubPromise.resolve(x) should yield an instance of SubPromise.

Yeah, and to be clear, I generally agree with this. My LabeledPromise example adheres to this. Other examples in related threads have been setting @@species to an entirely new constructor (e.g. to Promise itself), which is very strange to me. If you do that, you deserve whatever weirdness you might get, IMO. From the beginning, @@species has been about constructor signature modification.

> But I see your logic, indirecting through species provides a way for subclasses to to change their constructor signature and still work correctly with the other inherited Promise static methods. 

Any thoughts on Array.of and Array.from?
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

RE: Fixing `Promise.resolve()`

Domenic Denicola
In reply to this post by C. Scott Ananian

Yes, I read that thread and still stand by my position.

 

From: [hidden email] [mailto:[hidden email]] On Behalf Of C. Scott Ananian
Sent: Wednesday, June 10, 2015 11:39
To: Domenic Denicola
Cc: Allen Wirfs-Brock; Axel Rauschmayer; Mark S. Miller; es-discuss list
Subject: Re: Fixing `Promise.resolve()`

 

@Domenic: please see the previous discussion at https://esdiscuss.org/topic/subclassing-es6-objects-with-es5-syntax#content-50 since there is much more discussion back-and-forth there.

 

And you are correct about Promise.reject; Allen is proposing to remove the @@species from that method as well.

 

The changes to `Promise.resolve` are needed to make other use cases work properly (see that other thread).  It seems that your particular use case could be better handled by overriding `LabelledPromise.resolve` to take an additional "label" argument.

 

Your understanding of @@species seems to be different from the use cases envisioned by the smalltalk concept named species, although it's an interesting idea in its own right.  You should probably call it something like "custom constructors", though, to differentiate it from the smalltalk "species", which is used in the smalltalk world to describe two related things (1) the "generic type" of the object, for type tests, and (2) the "derived type" which instance-transformation methods should yield.[*]  In smalltalk (as I understand it) custom constructors are not part of the design.

  --scott

 

[*] ""Answer the preferred class for reconstructing the receiver. For example,  collections create new collections whenever enumeration messages such as collect: or select: are invoked. The new kind of collection is determined by the species of the original collection. Species and class are not always the  same. For example, the species of Interval is Array." http://forum.world.st/species-td3374278.html

 

On Wed, Jun 10, 2015 at 11:22 AM, Domenic Denicola <[hidden email]> wrote:

Allen, that change seems wrong. I thought we were only changing the IsPromise steps. The actual construction should still go through species. If nothing else, it should do so for consistency with reject.

The motivation of @@species, as I understood it, was to allow alternate subclass constructor signatures (originally for Array and TypedArray, but Promise can benefit as well). It’s understandable to not involve @@species when doing weak type-tests. But any time you construct a promise instance, you should go through @@species, instead of the constructor directly.

Some example usages:

- Creating a LabeledPromise subclass (for better debugging, like RSVP's promises + Ember promise inspector) whose constructor signature is `new LabeledPromise(label, executor)`
- Creating a SaneArray subclass whose constructor signature is `new SaneArray(...elements)` without the special-case for a single argument.
- A more complicated usage in a proposed Element/HTMLElement/MyCustomElement hierarchy [1], to allow custom elements to have custom constructor signatures but still work well with various element-creating parts of the platform.

The LabeledPromise case will, as currently specified, work great. LabeledPromise has a custom `LabeledPromise[Symbol.species](executor)` which basically does `return new this("<derived promise>", executor)`. Then it doesn't have to override `.resolve`, `.reject`, `.all`, or `.then`. However, with your change, `.resolve` will no longer work correctly, even though `.reject` will.

However, the SaneArray case actually will only work for the instance methods, which use ArraySpeciesCreate. In contrast, Array.of and Array.from use Construct(C, <<len>>). That seems like a bug in the spec?

[1]: https://github.com/domenic/element-constructors/blob/cdfe5a1d865e25d265074418df7918fda959e403/element-constructors.js#L101-L107

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

 


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Fixing `Promise.resolve()`

C. Scott Ananian
In reply to this post by Domenic Denicola
I don't agree that @@species is useful at all for changing constructor signatures, since there is no closure argument.

If we had dynamically scoped variables, then:
```
  LabelledPromise[Symbol.species] = function() { return LabelledPromise.bind(label/*dynamically scoped*/); };
  function() {
    let label = "foo";
    return LabelledPromise.resolve(x);
  }
```
would indeed be very interesting.  But in the absence of some sort of closure, the only way you can make @@species into a custom constructor is for odd special cases where you are just rearranging deck chairs.

Why not:
 ```
class LabelledPromise {
  constructor(exec, label) {
    super(exec);
    this.label = label === undefined ? "<derived promise>" : label;
  }
}
```
  --scott 


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

RE: Fixing `Promise.resolve()`

Domenic Denicola

Regardless of whether or not you agree, that was the original motivation for its introduction.

 

From: [hidden email] [mailto:[hidden email]] On Behalf Of C. Scott Ananian
Sent: Wednesday, June 10, 2015 11:45
To: Domenic Denicola
Cc: Allen Wirfs-Brock; Mark S. Miller; es-discuss list
Subject: Re: Fixing `Promise.resolve()`

 

I don't agree that @@species is useful at all for changing constructor signatures, since there is no closure argument.

 

If we had dynamically scoped variables, then:

```

  LabelledPromise[Symbol.species] = function() { return LabelledPromise.bind(label/*dynamically scoped*/); };

  function() {

    let label = "foo";

    return LabelledPromise.resolve(x);

  }

```

would indeed be very interesting.  But in the absence of some sort of closure, the only way you can make @@species into a custom constructor is for odd special cases where you are just rearranging deck chairs.

 

Why not:

 ```

class LabelledPromise {

  constructor(exec, label) {

    super(exec);

    this.label = label === undefined ? "<derived promise>" : label;

  }

}

```

  --scott 

 


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Fixing `Promise.resolve()`

C. Scott Ananian
On Wed, Jun 10, 2015 at 11:46 AM, Domenic Denicola <[hidden email]> wrote:

Regardless of whether or not you agree, that was the original motivation for its introduction.


ES6 final tweaks #8: Smalltalk-like species pattern used in Array methods, etc. to determine constructor for derived objects.
https://esdiscuss.org/notes/2014-11-18 discusses species in the context of `Array.prototype` methods.
Allen Wirfs-Brock: Smalltalk uses an abstract above that has a species property to determine what to create.

That's all I know of it.  I wasn't there, obviously, and you were.  But this is the first I've ever heard of using @@species for constructor signature modification.  It's hard to reconstruct reasoning from meeting notes and tweets.
  --scott


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Fixing `Promise.resolve()`

Mark S. Miller
In reply to this post by C. Scott Ananian
Independent of the current issue, I just want to go on record stating that dynamically scoped variables are a "cure" worse than any disease we might think to apply them to. Avoid at all costs.


On Wed, Jun 10, 2015 at 8:44 AM, C. Scott Ananian <[hidden email]> wrote:
I don't agree that @@species is useful at all for changing constructor signatures, since there is no closure argument.

If we had dynamically scoped variables, then:
```
  LabelledPromise[Symbol.species] = function() { return LabelledPromise.bind(label/*dynamically scoped*/); };
  function() {
    let label = "foo";
    return LabelledPromise.resolve(x);
  }
```
would indeed be very interesting.  But in the absence of some sort of closure, the only way you can make @@species into a custom constructor is for odd special cases where you are just rearranging deck chairs.

Why not:
 ```
class LabelledPromise {
  constructor(exec, label) {
    super(exec);
    this.label = label === undefined ? "<derived promise>" : label;
  }
}
```
  --scott 


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss




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

  Cheers,
  --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Fixing `Promise.resolve()`

Allen Wirfs-Brock
In reply to this post by C. Scott Ananian

On Jun 10, 2015, at 9:16 AM, C. Scott Ananian wrote:

On Wed, Jun 10, 2015 at 11:46 AM, Domenic Denicola <[hidden email]> wrote:

Regardless of whether or not you agree, that was the original motivation for its introduction.


ES6 final tweaks #8: Smalltalk-like species pattern used in Array methods, etc. to determine constructor for derived objects.
https://esdiscuss.org/notes/2014-11-18 discusses species in the context of `Array.prototype` methods.
Allen Wirfs-Brock: Smalltalk uses an abstract above that has a species property to determine what to create.

That's all I know of it.  I wasn't there, obviously, and you were.  But this is the first I've ever heard of using @@species for constructor signature modification.  It's hard to reconstruct reasoning from meeting notes and tweets.

That's correct.  `species` is intended for use when a subclass constructor wants to use something other than itself as the constructor for objects derived from the subclass instances.  Using `species` to select a constructor higher in a class hierarchy for derived instances is a fine thing to so.  For example, a "SortedArray" might choose that operations like `map` should produce the more general Array instances rather than SortedArray instances.

Using `species` to modify constructor signatures was not one of its intended use-cases, however, it might be possible to use it for that purpose.

Note that the uses of `species` in the ES6 spec all assume that the signature of the returned constructor is the same as the base class constructor. 

However, a way around that might be to have a `species` method that was an adaptor of the expected constructor signature to some other signature pattern. 

For example, 
   
  LabelledPromise[Symbol.species] = function() {
       ctor = this;
       return function(executor) {
            if (new.target === undefined) throw TypeError("Can't call a class constructor");
            return Reflect.construct(ctor, [ctor.defaultLabel, executor], new.target)
       }
  };
LabelledPromise.defaultLabel = "default label";

Allen
 






_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss