Discussion:
Array.from API
Dmitry Soshnikov
2014-10-07 02:59:32 UTC
Permalink
Hi,

We're currently polyfilling `Array.from` in our codebase following the
latest draft [1]. And I was actually surprised by the `mapfn` being
involved into the algorithm.

I mean, from the performance perspective it's probably .. ok-ish.. but from
the API design perspective it feels like combining the actual
transformation of an iterable (or of an array-like) with the mapping, is
the "too much of responsibility" anti-pattern. Why not filter then as well?
(or, as one of the comments on a diff review: "I'm actually disappointed it
won't do my laundry as well :P").

It probably should be just:

```
Array.from(...).map(mapfn);
```

Unless I'm missing something, and there was a special reason to include the
mapping.

Dmitry

[1] https://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.from
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141006/68804c36/attachment.html>
Rick Waldron
2014-10-07 03:19:04 UTC
Permalink
On Mon, Oct 6, 2014 at 10:59 PM, Dmitry Soshnikov <
Post by Dmitry Soshnikov
Hi,
We're currently polyfilling `Array.from` in our codebase following the
latest draft [1]. And I was actually surprised by the `mapfn` being
involved into the algorithm.
Have you tried es6-shim?
Post by Dmitry Soshnikov
I mean, from the performance perspective it's probably .. ok-ish.. but
from the API design perspective it feels like combining the actual
transformation of an iterable (or of an array-like) with the mapping, is
the "too much of responsibility" anti-pattern. Why not filter then as well?
(or, as one of the comments on a diff review: "I'm actually disappointed
it won't do my laundry as well :P").
```
Array.from(...).map(mapfn);
```
Unless I'm missing something, and there was a special reason to include
the mapping.
Yes:
https://github.com/rwaldron/tc39-notes/blob/c61f48cea5f2339a1ec65ca89827c8cff170779b/es6/2013-01/jan-30.md#revising-the-array-subclassing-kind-issue
Any subclass of array will want to produce a list of its own "kind", but
.map returns an Array. This thread is also a dup of:
https://mail.mozilla.org/pipermail/es-discuss/2013-June/031500.html

Rick
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141006/8afbec55/attachment.html>
Rick Waldron
2014-10-07 03:19:55 UTC
Permalink
On Mon, Oct 6, 2014 at 11:19 PM, Rick Waldron <waldron.rick at gmail.com>
Post by Rick Waldron
On Mon, Oct 6, 2014 at 10:59 PM, Dmitry Soshnikov <
Post by Dmitry Soshnikov
Hi,
We're currently polyfilling `Array.from` in our codebase following the
latest draft [1]. And I was actually surprised by the `mapfn` being
involved into the algorithm.
Have you tried es6-shim?
Post by Dmitry Soshnikov
I mean, from the performance perspective it's probably .. ok-ish.. but
from the API design perspective it feels like combining the actual
transformation of an iterable (or of an array-like) with the mapping, is
the "too much of responsibility" anti-pattern. Why not filter then as well?
(or, as one of the comments on a diff review: "I'm actually disappointed
it won't do my laundry as well :P").
```
Array.from(...).map(mapfn);
```
Unless I'm missing something, and there was a special reason to include
the mapping.
https://github.com/rwaldron/tc39-notes/blob/c61f48cea5f2339a1ec65ca89827c8cff170779b/es6/2013-01/jan-30.md#revising-the-array-subclassing-kind-issue
Any subclass of array will want to produce a list of its own "kind", but
https://mail.mozilla.org/pipermail/es-discuss/2013-June/031500.html
And
https://esdiscuss.org/topic/array-subclassing-map-and-iterables-re-jan-30-tc39-meeting-notes#content-0

Rick
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141006/dde0fb63/attachment.html>
Dmitry Soshnikov
2014-10-07 05:48:36 UTC
Permalink
Post by Rick Waldron
On Mon, Oct 6, 2014 at 10:59 PM, Dmitry Soshnikov <
Post by Dmitry Soshnikov
Hi,
We're currently polyfilling `Array.from` in our codebase following the
latest draft [1]. And I was actually surprised by the `mapfn` being
involved into the algorithm.
Have you tried es6-shim?
Yeah, I'm aware of it, though, we have own versions for better performance,
since may skip some internal checks, etc.
Post by Rick Waldron
Post by Dmitry Soshnikov
I mean, from the performance perspective it's probably .. ok-ish.. but
from the API design perspective it feels like combining the actual
transformation of an iterable (or of an array-like) with the mapping, is
the "too much of responsibility" anti-pattern. Why not filter then as well?
(or, as one of the comments on a diff review: "I'm actually disappointed
it won't do my laundry as well :P").
```
Array.from(...).map(mapfn);
```
Unless I'm missing something, and there was a special reason to include
the mapping.
https://github.com/rwaldron/tc39-notes/blob/c61f48cea5f2339a1ec65ca89827c8cff170779b/es6/2013-01/jan-30.md#revising-the-array-subclassing-kind-issue
Any subclass of array will want to produce a list of its own "kind", but
https://mail.mozilla.org/pipermail/es-discuss/2013-June/031500.html
I see. OK, thanks Rick, will re-read.

Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141006/958f5286/attachment-0001.html>
C. Scott Ananian
2014-10-07 13:17:08 UTC
Permalink
On Tue, Oct 7, 2014 at 1:48 AM, Dmitry Soshnikov
Post by Dmitry Soshnikov
Post by Rick Waldron
On Mon, Oct 6, 2014 at 10:59 PM, Dmitry Soshnikov
Post by Dmitry Soshnikov
We're currently polyfilling `Array.from` in our codebase following the
latest draft [1]. And I was actually surprised by the `mapfn` being involved
into the algorithm.
Have you tried es6-shim?
Yeah, I'm aware of it, though, we have own versions for better performance,
since may skip some internal checks, etc.
(Speaking as an es6-shim maintainer) I'm always interested in
benchmark results and performance patches. Are the ES6-required
checks really slowing you down? I would think that most JITs and CPUs
handle infrequently-taken branches pretty well these days.
--scott
Dmitry Soshnikov
2014-10-07 18:32:27 UTC
Permalink
On Tue, Oct 7, 2014 at 6:17 AM, C. Scott Ananian <ecmascript at cscott.net>
Post by C. Scott Ananian
On Tue, Oct 7, 2014 at 1:48 AM, Dmitry Soshnikov
On Mon, Oct 6, 2014 at 8:19 PM, Rick Waldron <waldron.rick at gmail.com>
Post by Rick Waldron
On Mon, Oct 6, 2014 at 10:59 PM, Dmitry Soshnikov
Post by Dmitry Soshnikov
We're currently polyfilling `Array.from` in our codebase following the
latest draft [1]. And I was actually surprised by the `mapfn` being
involved
Post by Rick Waldron
Post by Dmitry Soshnikov
into the algorithm.
Have you tried es6-shim?
Yeah, I'm aware of it, though, we have own versions for better
performance,
since may skip some internal checks, etc.
(Speaking as an es6-shim maintainer) I'm always interested in
benchmark results and performance patches. Are the ES6-required
checks really slowing you down? I would think that most JITs and CPUs
handle infrequently-taken branches pretty well these days.
The `es6-shim` is written well, though the performance is not the only
reason. We have own modules and polyfilling system, and don't polyfill
every single thing (just needed), so it's easier to write own.

Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141007/c6de8bac/attachment.html>
Dmitry Soshnikov
2014-10-07 18:36:47 UTC
Permalink
On Mon, Oct 6, 2014 at 10:48 PM, Dmitry Soshnikov <
Post by Dmitry Soshnikov
Post by Rick Waldron
On Mon, Oct 6, 2014 at 10:59 PM, Dmitry Soshnikov <
Post by Dmitry Soshnikov
Hi,
We're currently polyfilling `Array.from` in our codebase following the
latest draft [1]. And I was actually surprised by the `mapfn` being
involved into the algorithm.
Have you tried es6-shim?
Yeah, I'm aware of it, though, we have own versions for better
performance, since may skip some internal checks, etc.
Post by Rick Waldron
Post by Dmitry Soshnikov
I mean, from the performance perspective it's probably .. ok-ish.. but
from the API design perspective it feels like combining the actual
transformation of an iterable (or of an array-like) with the mapping, is
the "too much of responsibility" anti-pattern. Why not filter then as well?
(or, as one of the comments on a diff review: "I'm actually
disappointed it won't do my laundry as well :P").
```
Array.from(...).map(mapfn);
```
Unless I'm missing something, and there was a special reason to include
the mapping.
https://github.com/rwaldron/tc39-notes/blob/c61f48cea5f2339a1ec65ca89827c8cff170779b/es6/2013-01/jan-30.md#revising-the-array-subclassing-kind-issue
Any subclass of array will want to produce a list of its own "kind", but
https://mail.mozilla.org/pipermail/es-discuss/2013-June/031500.html
I see. OK, thanks Rick, will re-read.
OK, have checked. And guess I still don't see a big issue, as long as the
`Array.prototype.map` preserves the kind (by delegating to `new
this.constructor(...)`).

That specific example like:

```
NodeList.form(['div', 'span'], nodeName =>
document.createElement(nodeName));
```

arguing that the `NodeList` can't create elements from the strings doesn't
seems to me a good reason for introducing that anti-pattern, and it's
really should be rewritten as:

```
NodeList.form(['div', 'span'].map(nodeName =>
document.createElement(nodeName)));
```

And other things are better be written:

```
<ArrayKind>.from(iterable).map(mapfn)
```

Am I still missing something?

Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141007/bdcb3650/attachment.html>
Domenic Denicola
2014-10-07 18:46:50 UTC
Permalink
From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of Dmitry Soshnikov
Post by Dmitry Soshnikov
Am I still missing something?
Yes.

```js
var uint16s = new Uint16Array([258]);
var uint8s = Uint8Array.from(uint16s, x => x / 2);
console.log(uint8s); // [129]
```

```js
var uint16s = new Uint16Array([258]);
var uint8s = Uint8Array.from(uint16s).map(x => x / 2);
console.log(uint8s); // [1]
```
Dmitry Soshnikov
2014-10-07 18:57:49 UTC
Permalink
On Tue, Oct 7, 2014 at 11:46 AM, Domenic Denicola <
Post by Domenic Denicola
From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of Dmitry Soshnikov
Post by Dmitry Soshnikov
Am I still missing something?
Yes.
```js
var uint16s = new Uint16Array([258]);
var uint8s = Uint8Array.from(uint16s, x => x / 2);
console.log(uint8s); // [129]
```
```js
var uint16s = new Uint16Array([258]);
var uint8s = Uint8Array.from(uint16s).map(x => x / 2);
console.log(uint8s); // [1]
```
This seems the same "issue" as with the `NodeList`. The arguments for the
`from` should be anything that the constructor expects, if the `NodeList`
excepts a document node, it should be passed a document node, not a string.
I.e. the array should be mapped _before_ passing to the `from`.

```js
var uint16s = new Uint16Array([258]);
var uint8s = Uint8Array.from(uint16s.map(x => x / 2));
console.log(uint8s); // [129]
```

Is it?

Otherwise, we can back to the question why it doesn't do filter as well?

Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141007/66b474f1/attachment-0001.html>
Dmitry Soshnikov
2014-10-07 19:18:38 UTC
Permalink
On Tue, Oct 7, 2014 at 11:46 AM, Domenic Denicola <
Post by Domenic Denicola
From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of Dmitry Soshnikov
Post by Dmitry Soshnikov
Am I still missing something?
Yes.
```js
var uint16s = new Uint16Array([258]);
var uint8s = Uint8Array.from(uint16s, x => x / 2);
console.log(uint8s); // [129]
```
```js
var uint16s = new Uint16Array([258]);
var uint8s = Uint8Array.from(uint16s).map(x => x / 2);
console.log(uint8s); // [1]
```
Moreover, these two examples are semantically completely different. They
confuse and substitute the pre- and post- mapping. Clearly, it should be
pre-mapping here, and the second example is not even correct from this
perspective. And exactly manually pre-map it, is seems better, because that
`mapfn` on the API level can simply be confusing: what does it do -- maps
pre- or post?

And as mentioned above, after the correct list is constructed (with
possible pre-mapping), developers can also post-map it calling the
`Array.prototype.map` that still preserves the kind of the collection.

So I'd say, we should exclude the `mapfn` from `Array.from` in order to
keep the implementation (including polyfills) simpler and responsible for
only one things -- building a <ArrayKind> collection from another
collection or an iterable, consuming _correct_ data.

Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141007/c36f1a8d/attachment.html>
Claude Pache
2014-10-07 18:56:28 UTC
Permalink
Post by Dmitry Soshnikov
```
<ArrayKind>.from(iterable).map(mapfn)
```
Am I still missing something?
Yes: `UInt32Array.from(['a', 'b', 'c], x => x.codePointAt(0))`

?Claude
Dmitry Soshnikov
2014-10-07 18:59:02 UTC
Permalink
On Tue, Oct 7, 2014 at 11:56 AM, Claude Pache <claude.pache at gmail.com>
Post by Claude Pache
Le 7 oct. 2014 ? 20:36, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> a
```
<ArrayKind>.from(iterable).map(mapfn)
```
Am I still missing something?
Yes: `UInt32Array.from(['a', 'b', 'c], x => x.codePointAt(0))`
Still seems the same as `NodeList` "issue":

```
UInt32Array.from(['a', 'b', 'c].map(x => x.codePointAt(0)));
```

Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141007/86b2b15b/attachment.html>
Dmitry Soshnikov
2014-10-07 19:01:55 UTC
Permalink
On Tue, Oct 7, 2014 at 11:59 AM, Dmitry Soshnikov <
Post by Dmitry Soshnikov
On Tue, Oct 7, 2014 at 11:56 AM, Claude Pache <claude.pache at gmail.com>
Post by Claude Pache
Le 7 oct. 2014 ? 20:36, Dmitry Soshnikov <dmitry.soshnikov at gmail.com>
```
<ArrayKind>.from(iterable).map(mapfn)
```
Am I still missing something?
Yes: `UInt32Array.from(['a', 'b', 'c], x => x.codePointAt(0))`
```
UInt32Array.from(['a', 'b', 'c].map(x => x.codePointAt(0)));
```
And after you have fed the data the `UInt32Array` expects, you can post-map
it as well:


```
UInt32Array.from(['a', 'b', 'c].map(x => x.codePointAt(0))).map(v => v * 2);
```

What's is wrong in here? We don't have "too much of responsibility"
anti-pattern, explicitly separate the transformation form mapping, and
explicitly say what the format of data a particular constructor expects
(thus, mapping it before passing, as it should be).

Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141007/306c5bae/attachment.html>
Dmitry Soshnikov
2014-10-07 19:10:05 UTC
Permalink
On Tue, Oct 7, 2014 at 12:01 PM, Dmitry Soshnikov <
Post by Dmitry Soshnikov
On Tue, Oct 7, 2014 at 11:59 AM, Dmitry Soshnikov <
Post by Dmitry Soshnikov
On Tue, Oct 7, 2014 at 11:56 AM, Claude Pache <claude.pache at gmail.com>
Post by Claude Pache
Le 7 oct. 2014 ? 20:36, Dmitry Soshnikov <dmitry.soshnikov at gmail.com>
```
<ArrayKind>.from(iterable).map(mapfn)
```
Am I still missing something?
Yes: `UInt32Array.from(['a', 'b', 'c], x => x.codePointAt(0))`
```
UInt32Array.from(['a', 'b', 'c].map(x => x.codePointAt(0)));
```
And after you have fed the data the `UInt32Array` expects, you can
```
UInt32Array.from(['a', 'b', 'c].map(x => x.codePointAt(0))).map(v => v * 2);
```
What's is wrong in here? We don't have "too much of responsibility"
anti-pattern, explicitly separate the transformation form mapping, and
explicitly say what the format of data a particular constructor expects
(thus, mapping it before passing, as it should be).
And that's an iterable being passed to the from may not have the `map`
method doesn't seem to me a good reason either. Still this anti-pattern
feels worse.

Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141007/ca914b4d/attachment.html>
Rick Waldron
2014-10-07 19:22:52 UTC
Permalink
On Tue, Oct 7, 2014 at 3:01 PM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com
Post by Dmitry Soshnikov
On Tue, Oct 7, 2014 at 11:59 AM, Dmitry Soshnikov <
Post by Dmitry Soshnikov
On Tue, Oct 7, 2014 at 11:56 AM, Claude Pache <claude.pache at gmail.com>
Post by Claude Pache
Le 7 oct. 2014 ? 20:36, Dmitry Soshnikov <dmitry.soshnikov at gmail.com>
```
<ArrayKind>.from(iterable).map(mapfn)
```
Am I still missing something?
Yes: `UInt32Array.from(['a', 'b', 'c], x => x.codePointAt(0))`
```
UInt32Array.from(['a', 'b', 'c].map(x => x.codePointAt(0)));
```
And after you have fed the data the `UInt32Array` expects, you can
```
UInt32Array.from(['a', 'b', 'c].map(x => x.codePointAt(0))).map(v => v * 2);
```
What's is wrong in here?
That example will allocate 2 additional objects; the following version of
the same operation will allocate _zero_ additional objects:

UInt32Array.from(['a', 'b', 'c], x => x.codePointAt(0) * 2);



Rick
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141007/b8de39cf/attachment.html>
Dmitry Soshnikov
2014-10-07 19:25:43 UTC
Permalink
On Tue, Oct 7, 2014 at 12:22 PM, Rick Waldron <waldron.rick at gmail.com>
Post by Rick Waldron
On Tue, Oct 7, 2014 at 3:01 PM, Dmitry Soshnikov <
Post by Dmitry Soshnikov
On Tue, Oct 7, 2014 at 11:59 AM, Dmitry Soshnikov <
Post by Dmitry Soshnikov
On Tue, Oct 7, 2014 at 11:56 AM, Claude Pache <claude.pache at gmail.com>
Post by Claude Pache
Le 7 oct. 2014 ? 20:36, Dmitry Soshnikov <dmitry.soshnikov at gmail.com>
```
<ArrayKind>.from(iterable).map(mapfn)
```
Am I still missing something?
Yes: `UInt32Array.from(['a', 'b', 'c], x => x.codePointAt(0))`
```
UInt32Array.from(['a', 'b', 'c].map(x => x.codePointAt(0)));
```
And after you have fed the data the `UInt32Array` expects, you can
```
UInt32Array.from(['a', 'b', 'c].map(x => x.codePointAt(0))).map(v => v * 2);
```
What's is wrong in here?
That example will allocate 2 additional objects; the following version of
UInt32Array.from(['a', 'b', 'c], x => x.codePointAt(0) * 2);
Exactly. And this is what I mentioned at the beginning: the performance
reasons shouldn't (never) overweight in "good API design" topics.

Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141007/ed0f992a/attachment-0001.html>
Dmitry Soshnikov
2014-10-07 19:27:19 UTC
Permalink
On Tue, Oct 7, 2014 at 12:25 PM, Dmitry Soshnikov <
Post by Dmitry Soshnikov
On Tue, Oct 7, 2014 at 12:22 PM, Rick Waldron <waldron.rick at gmail.com>
Post by Rick Waldron
On Tue, Oct 7, 2014 at 3:01 PM, Dmitry Soshnikov <
Post by Dmitry Soshnikov
On Tue, Oct 7, 2014 at 11:59 AM, Dmitry Soshnikov <
Post by Dmitry Soshnikov
On Tue, Oct 7, 2014 at 11:56 AM, Claude Pache <claude.pache at gmail.com>
Post by Claude Pache
Le 7 oct. 2014 ? 20:36, Dmitry Soshnikov <dmitry.soshnikov at gmail.com>
```
<ArrayKind>.from(iterable).map(mapfn)
```
Am I still missing something?
Yes: `UInt32Array.from(['a', 'b', 'c], x => x.codePointAt(0))`
```
UInt32Array.from(['a', 'b', 'c].map(x => x.codePointAt(0)));
```
And after you have fed the data the `UInt32Array` expects, you can
```
UInt32Array.from(['a', 'b', 'c].map(x => x.codePointAt(0))).map(v => v * 2);
```
What's is wrong in here?
That example will allocate 2 additional objects; the following version of
UInt32Array.from(['a', 'b', 'c], x => x.codePointAt(0) * 2);
Exactly. And this is what I mentioned at the beginning: the performance
reasons shouldn't (never) overweight in "good API design" topics.
Since the next question will be: where is filter? It allows not allocating
stuff at all. However, we won't mention whether it's an anti-pattern or
not, since it goes without saying.

Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141007/7a260d0f/attachment.html>
Dmitry Soshnikov
2014-10-07 19:32:21 UTC
Permalink
On Tue, Oct 7, 2014 at 12:27 PM, Dmitry Soshnikov <
Post by Dmitry Soshnikov
On Tue, Oct 7, 2014 at 12:25 PM, Dmitry Soshnikov <
On Tue, Oct 7, 2014 at 12:22 PM, Rick Waldron <waldron.rick at gmail.com>
Post by Dmitry Soshnikov
Post by Rick Waldron
On Tue, Oct 7, 2014 at 3:01 PM, Dmitry Soshnikov <
Post by Dmitry Soshnikov
On Tue, Oct 7, 2014 at 11:59 AM, Dmitry Soshnikov <
Post by Dmitry Soshnikov
On Tue, Oct 7, 2014 at 11:56 AM, Claude Pache <claude.pache at gmail.com>
Post by Claude Pache
Le 7 oct. 2014 ? 20:36, Dmitry Soshnikov <
```
<ArrayKind>.from(iterable).map(mapfn)
```
Am I still missing something?
Yes: `UInt32Array.from(['a', 'b', 'c], x => x.codePointAt(0))`
```
UInt32Array.from(['a', 'b', 'c].map(x => x.codePointAt(0)));
```
And after you have fed the data the `UInt32Array` expects, you can
```
UInt32Array.from(['a', 'b', 'c].map(x => x.codePointAt(0))).map(v => v * 2);
```
What's is wrong in here?
That example will allocate 2 additional objects; the following version
UInt32Array.from(['a', 'b', 'c], x => x.codePointAt(0) * 2);
Exactly. And this is what I mentioned at the beginning: the performance
reasons shouldn't (never) overweight in "good API design" topics.
Since the next question will be: where is filter? It allows not allocating
stuff at all. However, we won't mention whether it's an anti-pattern or
not, since it goes without saying.
I mean, yeah, we can accept and live with this -- aka, yeah why not, it's
convenient in place to pre-map, and good for cases when an iterable doesn't
have the `map`, and it's good for performance. But all the things from
above stands: it's confusing since doesn't explain whether it's pre- or
post- map, and takes too much at implementation.

Otherwise, I think it can be there, as long as it was approved already.
Worth though considering this in the future API designs: the performance
shouldn't drive the API.

Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141007/cfbf2c77/attachment.html>
Tab Atkins Jr.
2014-10-07 19:50:37 UTC
Permalink
On Tue, Oct 7, 2014 at 12:32 PM, Dmitry Soshnikov
Post by Dmitry Soshnikov
I mean, yeah, we can accept and live with this -- aka, yeah why not, it's
convenient in place to pre-map, and good for cases when an iterable doesn't
have the `map`, and it's good for performance. But all the things from above
stands: it's confusing since doesn't explain whether it's pre- or post- map,
and takes too much at implementation.
Alternately, you can just consider Foo.from to be the method version
of a comprehension - you can feed it any iterable and transform the
value arbitrarily before putting it into the new collection. That
does suggest that a filter argument would also be useful, as you've
said.

~TJ
Dmitry Soshnikov
2014-10-07 19:53:01 UTC
Permalink
On Tue, Oct 7, 2014 at 12:50 PM, Tab Atkins Jr. <jackalmage at gmail.com>
Post by Tab Atkins Jr.
On Tue, Oct 7, 2014 at 12:32 PM, Dmitry Soshnikov
Post by Dmitry Soshnikov
I mean, yeah, we can accept and live with this -- aka, yeah why not, it's
convenient in place to pre-map, and good for cases when an iterable
doesn't
Post by Dmitry Soshnikov
have the `map`, and it's good for performance. But all the things from
above
Post by Dmitry Soshnikov
stands: it's confusing since doesn't explain whether it's pre- or post-
map,
Post by Dmitry Soshnikov
and takes too much at implementation.
Alternately, you can just consider Foo.from to be the method version
of a comprehension - you can feed it any iterable and transform the
value arbitrarily before putting it into the new collection. That
does suggest that a filter argument would also be useful, as you've
said
Yes, the list comprehensions is the thing that came to me in mind as well.

P.S> @all: Also, I apologize I posted to many replies guys above. I wish I
could edit/combine them, but can't in the email. Hope it's not considered
as spam ;)

Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141007/4368fe60/attachment-0001.html>
Claude Pache
2014-10-07 20:20:55 UTC
Permalink
But all the things from above stands: it's confusing since doesn't explain whether it's pre- or post- map, and takes too much at implementation.
My previous example could have been written as: `UInt32Array.from('abc', x => x.codePointAt(0))` (recalling that strings are iterable in ES6). My mapping is neither a pre-, nor a post-map. It's just a map which transforms a kind of value (a Unicode character) into another kind of value (a 32-bit integer).

?Claude
Dmitry Soshnikov
2014-10-07 20:39:49 UTC
Permalink
Le 7 oct. 2014 ? 21:32, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> a
But all the things from above stands: it's confusing since doesn't
explain whether it's pre- or post- map, and takes too much at
implementation.
My previous example could have been written as: `UInt32Array.from('abc', x
=> x.codePointAt(0))` (recalling that strings are iterable in ES6). My
mapping is neither a pre-, nor a post-map. It's just a map which transforms
a kind of value (a Unicode character) into another kind of value (a 32-bit
integer).
This code example is a good justification of the "an iterable doesn't have
own `map` method", but other than that, it's clearly pre-mapping, since
each element of the result is mapped before being set. The code is
semantically equivalent to:

```
UInt32Array.from('abc'.toArray().map(x => x.codePointAt(0));
```

Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141007/098dbd6a/attachment.html>
Bergi
2014-10-07 20:45:18 UTC
Permalink
I think all of the above examples are trying to create a case such as

| UInt32Array.from(nodelist, node => parseInt(node.value, 10) );

where neither can nodes be stored in an Uint32Array nor integers be
stored in a NodeList.

This might happen quite often, as `from` seems to be the "type casting"
operator ArrayA<X> -> ArrayB<Y> type - and if we cannot rely on implicit
casting, we need a X -> Y converter function.
A go-around to the "least common ancestor" array type that can store
both Xs and Ys is cumbersome. (And I'm not looking on performance, just
about clarity/conciseness).
Post by Dmitry Soshnikov
Since the next question will be: where is filter?
Good question. I guess however that since this does only concern the Y
type that the ArrayB can store, it would be built-into that ArrayB<Y>
constructor that we cast to.
E.g. typed arrays are known to clamp or take modulos of the passed
values; if you really wanted to completely omit passed values you'd
rather overwrite the `.from` method as a whole instead of relying on the
inherited one.

Bergi
Dmitry Soshnikov
2014-10-07 21:11:37 UTC
Permalink
Post by Bergi
I think all of the above examples are trying to create a case such as
| UInt32Array.from(nodelist, node => parseInt(node.value, 10) );
where neither can nodes be stored in an Uint32Array nor integers be stored
in a NodeList.
Not sure what you mean by "nor integers be stored in a NodeList", but how
does your example differ from:

```
UInt32Array.from(nodeList.map(node => parseInt(node.value, 10)));
```

Anyhow, seems the only good reason (IMO) here is "an iterable may not have
own `map` method", and we can live with that. And the broken and confusing
examples (when a post-map is substituted to the place of a clear pre-map)
do not help that much. Otherwise, I'd remove the `mapfn` from `Array.from`
(unless to turn it into a comprehensions API and accept the filter as well).

Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141007/5f4cce19/attachment.html>
Tab Atkins Jr.
2014-10-07 21:20:36 UTC
Permalink
On Tue, Oct 7, 2014 at 2:11 PM, Dmitry Soshnikov
Post by Dmitry Soshnikov
Post by Bergi
I think all of the above examples are trying to create a case such as
| UInt32Array.from(nodelist, node => parseInt(node.value, 10) );
where neither can nodes be stored in an Uint32Array nor integers be stored
in a NodeList.
Not sure what you mean by "nor integers be stored in a NodeList", but how
He meant that, assuming NodeList had a .map() that returned another
NodeList (in general, assuming that .map() is type-preserving, which
it's not currently), you wouldn't be able to easily do a "map it
first, then translate into the new collection" - you'd have to
explicitly translate it into a collection that can hold both UInt32
and Node values, then map, then translate.
Post by Dmitry Soshnikov
```
UInt32Array.from(nodeList.map(node => parseInt(node.value, 10)));
```
This works because .map() is not type-preserving, and automatically
produces an Array (which can accept anything).

~TJ
Dmitry Soshnikov
2014-10-07 21:26:19 UTC
Permalink
Post by Tab Atkins Jr.
On Tue, Oct 7, 2014 at 2:11 PM, Dmitry Soshnikov
Post by Dmitry Soshnikov
Post by Bergi
I think all of the above examples are trying to create a case such as
| UInt32Array.from(nodelist, node => parseInt(node.value, 10) );
where neither can nodes be stored in an Uint32Array nor integers be
stored
Post by Dmitry Soshnikov
Post by Bergi
in a NodeList.
Not sure what you mean by "nor integers be stored in a NodeList", but how
He meant that, assuming NodeList had a .map() that returned another
NodeList (in general, assuming that .map() is type-preserving, which
it's not currently), you wouldn't be able to easily do a "map it
first, then translate into the new collection" - you'd have to
explicitly translate it into a collection that can hold both UInt32
and Node values, then map, then translate.
Post by Dmitry Soshnikov
```
UInt32Array.from(nodeList.map(node => parseInt(node.value, 10)));
```
This works because .map() is not type-preserving, and automatically
produces an Array (which can accept anything).
I see. Actually it doesn't work, your're correct, since
`Array.prototype.map` does preserve the kind (at least in the latest
draft). And the `UInt32Array.from(...)` would be consuming a nodeList, not
an array. Will the `nodeList.map(node => parseInt(node.value, 10));` by
itself actually work then?

Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141007/e6e57de0/attachment.html>
Tab Atkins Jr.
2014-10-07 21:35:52 UTC
Permalink
On Tue, Oct 7, 2014 at 2:26 PM, Dmitry Soshnikov
Post by Dmitry Soshnikov
I see. Actually it doesn't work, your're correct, since
`Array.prototype.map` does preserve the kind (at least in the latest draft).
Hmm, per Rick's earlier email and
<https://github.com/rwaldron/tc39-notes/blob/c61f48cea5f2339a1ec65ca89827c8cff170779b/es6/2013-01/jan-30.md#revising-the-array-subclassing-kind-issue>,
Array#map (used by a subclass) doesn't preserve the subclass's type;
it always returns an Array.
Post by Dmitry Soshnikov
And the `UInt32Array.from(...)` would be consuming a nodeList, not an array.
Will the `nodeList.map(node => parseInt(node.value, 10));` by itself
actually work then?
If .map() is inherited from Array, and thus not type-preserving, yes,
it'll work.

~TJ
Dmitry Soshnikov
2014-10-07 21:43:52 UTC
Permalink
Post by Tab Atkins Jr.
On Tue, Oct 7, 2014 at 2:26 PM, Dmitry Soshnikov
Post by Dmitry Soshnikov
I see. Actually it doesn't work, your're correct, since
`Array.prototype.map` does preserve the kind (at least in the latest
draft).
Hmm, per Rick's earlier email and
<
https://github.com/rwaldron/tc39-notes/blob/c61f48cea5f2339a1ec65ca89827c8cff170779b/es6/2013-01/jan-30.md#revising-the-array-subclassing-kind-issue
Post by Dmitry Soshnikov
,
Array#map (used by a subclass) doesn't preserve the subclass's type;
it always returns an Array.
Post by Dmitry Soshnikov
And the `UInt32Array.from(...)` would be consuming a nodeList, not an
array.
Post by Dmitry Soshnikov
Will the `nodeList.map(node => parseInt(node.value, 10));` by itself
actually work then?
If .map() is inherited from Array, and thus not type-preserving, yes,
it'll work.
Yes, it is preserving (probably was changed since that previous
discussion), see (9) in
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.prototype.map.
Will a simple map to `node.value` on a `NodeList` work with the preserving
`Array#map`?

Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141007/3594b6f1/attachment.html>
Claude Pache
2014-10-07 23:08:07 UTC
Permalink
Post by Tab Atkins Jr.
On Tue, Oct 7, 2014 at 2:26 PM, Dmitry Soshnikov
Post by Dmitry Soshnikov
I see. Actually it doesn't work, your're correct, since
`Array.prototype.map` does preserve the kind (at least in the latest draft).
Hmm, per Rick's earlier email and
<https://github.com/rwaldron/tc39-notes/blob/c61f48cea5f2339a1ec65ca89827c8cff170779b/es6/2013-01/jan-30.md#revising-the-array-subclassing-kind-issue>,
Array#map (used by a subclass) doesn't preserve the subclass's type;
it always returns an Array.
Post by Dmitry Soshnikov
And the `UInt32Array.from(...)` would be consuming a nodeList, not an array.
Will the `nodeList.map(node => parseInt(node.value, 10));` by itself
actually work then?
If .map() is inherited from Array, and thus not type-preserving, yes,
it'll work.
Yes, it is preserving (probably was changed since that previous discussion), see (9) in http://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.prototype.map. Will a simple map to `node.value` on a `NodeList` work with the preserving `Array#map`?
So, a `SortOfArray.from` (with a mapping) is finally less confusing than a `SortOfArray#map`, for you don't have to look at the doc in order to determine the type of the result... :-p

?Claude

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141008/ba83a63b/attachment.html>
Dmitry Soshnikov
2014-10-08 21:42:18 UTC
Permalink
Post by Dmitry Soshnikov
Post by Tab Atkins Jr.
On Tue, Oct 7, 2014 at 2:26 PM, Dmitry Soshnikov
Post by Dmitry Soshnikov
I see. Actually it doesn't work, your're correct, since
`Array.prototype.map` does preserve the kind (at least in the latest
draft).
Hmm, per Rick's earlier email and
<
https://github.com/rwaldron/tc39-notes/blob/c61f48cea5f2339a1ec65ca89827c8cff170779b/es6/2013-01/jan-30.md#revising-the-array-subclassing-kind-issue
Post by Dmitry Soshnikov
,
Array#map (used by a subclass) doesn't preserve the subclass's type;
it always returns an Array.
Post by Dmitry Soshnikov
And the `UInt32Array.from(...)` would be consuming a nodeList, not an
array.
Post by Dmitry Soshnikov
Will the `nodeList.map(node => parseInt(node.value, 10));` by itself
actually work then?
If .map() is inherited from Array, and thus not type-preserving, yes,
it'll work.
Yes, it is preserving (probably was changed since that previous
discussion), see (9) in
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.prototype.map.
Will a simple map to `node.value` on a `NodeList` work with the preserving
`Array#map`?
So, a `SortOfArray.from` (with a mapping) is finally less confusing than a `SortOfArray#map`,
for you don't have to look at the doc in order to determine the type of the
result... :-p
Also related, and came on Twitter just not:
https://twitter.com/DmitrySoshnikov/status/519964146637737986

The mapping function from `Array.from` considers holes (from the new TC39
"policy"), but `Array#map` does not.
Post by Dmitry Soshnikov
More clearly, Array.from(obj, mapFn, thisArg) is the same as
Array.from(obj).map(mapFn, thisArg), except that it does not create an
intermediate array.

Since not only they are "the same" (as we confuse/substitute pre- and post-
mapping), but also the mapping function itself behaves differently.

[1]
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from

Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141008/d949a055/attachment.html>
Dmitry Soshnikov
2014-10-08 21:47:25 UTC
Permalink
On Wed, Oct 8, 2014 at 2:42 PM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com
Post by Dmitry Soshnikov
Post by Dmitry Soshnikov
Post by Tab Atkins Jr.
On Tue, Oct 7, 2014 at 2:26 PM, Dmitry Soshnikov
Post by Dmitry Soshnikov
I see. Actually it doesn't work, your're correct, since
`Array.prototype.map` does preserve the kind (at least in the latest
draft).
Hmm, per Rick's earlier email and
<
https://github.com/rwaldron/tc39-notes/blob/c61f48cea5f2339a1ec65ca89827c8cff170779b/es6/2013-01/jan-30.md#revising-the-array-subclassing-kind-issue
Post by Dmitry Soshnikov
,
Array#map (used by a subclass) doesn't preserve the subclass's type;
it always returns an Array.
Post by Dmitry Soshnikov
And the `UInt32Array.from(...)` would be consuming a nodeList, not an
array.
Post by Dmitry Soshnikov
Will the `nodeList.map(node => parseInt(node.value, 10));` by itself
actually work then?
If .map() is inherited from Array, and thus not type-preserving, yes,
it'll work.
Yes, it is preserving (probably was changed since that previous
discussion), see (9) in
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.prototype.map.
Will a simple map to `node.value` on a `NodeList` work with the preserving
`Array#map`?
So, a `SortOfArray.from` (with a mapping) is finally less confusing than
a `SortOfArray#map`, for you don't have to look at the doc in order to
determine the type of the result... :-p
https://twitter.com/DmitrySoshnikov/status/519964146637737986
The mapping function from `Array.from` considers holes (from the new TC39
"policy"), but `Array#map` does not.
Post by Dmitry Soshnikov
More clearly, Array.from(obj, mapFn, thisArg) is the same as
Array.from(obj).map(mapFn, thisArg), except that it does not create an
intermediate array.
Since not only they are "the same" (as we confuse/substitute pre- and
post- mapping), but also the mapping function itself behaves differently.
[1]
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
Never mind, as Rick and Allen clarified, they will produce the same arrays,
because of behavior of `Array.from` which as a result already has a hole
converted to explicit `undefined` value. Here is an example:
http://gyazo.com/4709305f3bde1c8ce0b02d2071a99e7f

Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141008/25ef2604/attachment.html>
Dmitry Soshnikov
2014-10-09 02:55:24 UTC
Permalink
On Wed, Oct 8, 2014 at 2:47 PM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com
Post by Dmitry Soshnikov
On Wed, Oct 8, 2014 at 2:42 PM, Dmitry Soshnikov <
Post by Dmitry Soshnikov
Post by Dmitry Soshnikov
Post by Tab Atkins Jr.
On Tue, Oct 7, 2014 at 2:26 PM, Dmitry Soshnikov
Post by Dmitry Soshnikov
I see. Actually it doesn't work, your're correct, since
`Array.prototype.map` does preserve the kind (at least in the latest
draft).
Hmm, per Rick's earlier email and
<
https://github.com/rwaldron/tc39-notes/blob/c61f48cea5f2339a1ec65ca89827c8cff170779b/es6/2013-01/jan-30.md#revising-the-array-subclassing-kind-issue
Post by Dmitry Soshnikov
,
Array#map (used by a subclass) doesn't preserve the subclass's type;
it always returns an Array.
Post by Dmitry Soshnikov
And the `UInt32Array.from(...)` would be consuming a nodeList, not an
array.
Post by Dmitry Soshnikov
Will the `nodeList.map(node => parseInt(node.value, 10));` by itself
actually work then?
If .map() is inherited from Array, and thus not type-preserving, yes,
it'll work.
Yes, it is preserving (probably was changed since that previous
discussion), see (9) in
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.prototype.map.
Will a simple map to `node.value` on a `NodeList` work with the preserving
`Array#map`?
So, a `SortOfArray.from` (with a mapping) is finally less confusing than
a `SortOfArray#map`, for you don't have to look at the doc in order to
determine the type of the result... :-p
https://twitter.com/DmitrySoshnikov/status/519964146637737986
The mapping function from `Array.from` considers holes (from the new TC39
"policy"), but `Array#map` does not.
Post by Dmitry Soshnikov
More clearly, Array.from(obj, mapFn, thisArg) is the same as
Array.from(obj).map(mapFn, thisArg), except that it does not create an
intermediate array.
Since not only they are "the same" (as we confuse/substitute pre- and
post- mapping), but also the mapping function itself behaves differently.
[1]
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
Never mind, as Rick and Allen clarified, they will produce the same
arrays, because of behavior of `Array.from` which as a result already has a
http://gyazo.com/4709305f3bde1c8ce0b02d2071a99e7f
However, these are two different semantics, although are both pre-mapping:

```
Array.from([1,,2].map(x=>x*x)); // [1, 4]
Array.from([1,,2],x=>x*x); // [1, NaN, 4]
```

Dmitry
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141008/65fe582a/attachment.html>
Loading...