Array.from API

# Dmitry Soshnikov (11 years ago)

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] people.mozilla.org/~jorendorff/es6-draft.html#sec-array.from

# Rick Waldron (11 years ago)

On Mon, Oct 6, 2014 at 10:59 PM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:

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?

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.

Yes: 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: esdiscuss/2013-June/031500

# Rick Waldron (11 years ago)

On Mon, Oct 6, 2014 at 11:19 PM, Rick Waldron <waldron.rick at gmail.com>

wrote:

On Mon, Oct 6, 2014 at 10:59 PM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:

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?

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.

Yes: 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: esdiscuss/2013-June/031500

And esdiscuss.org/topic/array-subclassing-map-and-iterables-re-jan-30-tc39-meeting-notes#content

# Dmitry Soshnikov (11 years ago)

On Mon, Oct 6, 2014 at 8:19 PM, Rick Waldron <waldron.rick at gmail.com> wrote:

On Mon, Oct 6, 2014 at 10:59 PM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:

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.

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.

Yes: 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: esdiscuss/2013-June/031500

I see. OK, thanks Rick, will re-read.

Dmitry

# C. Scott Ananian (11 years ago)

On Tue, Oct 7, 2014 at 1:48 AM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> wrote:

On Mon, Oct 6, 2014 at 8:19 PM, Rick Waldron <waldron.rick at gmail.com> wrote:

On Mon, Oct 6, 2014 at 10:59 PM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> wrote:

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.

# Dmitry Soshnikov (11 years ago)

On Tue, Oct 7, 2014 at 6:17 AM, C. Scott Ananian <ecmascript at cscott.net>

wrote:

On Tue, Oct 7, 2014 at 1:48 AM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> wrote:

On Mon, Oct 6, 2014 at 8:19 PM, Rick Waldron <waldron.rick at gmail.com> wrote:

On Mon, Oct 6, 2014 at 10:59 PM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> wrote:

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.

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

# Dmitry Soshnikov (11 years ago)

On Mon, Oct 6, 2014 at 10:48 PM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:

On Mon, Oct 6, 2014 at 8:19 PM, Rick Waldron <waldron.rick at gmail.com> wrote:

On Mon, Oct 6, 2014 at 10:59 PM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:

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.

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.

Yes: 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: esdiscuss/2013-June/031500

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

# Domenic Denicola (11 years ago)

From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of Dmitry Soshnikov

Am I still missing something?

Yes.

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

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

console.log(uint8s); // [1]
# Claude Pache (11 years ago)

Le 7 oct. 2014 à 20:36, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> a écrit :

And other things are better be written:

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

Am I still missing something?

Yes: UInt32Array.from(['a', 'b', 'c], x => x.codePointAt(0))

# Dmitry Soshnikov (11 years ago)

On Tue, Oct 7, 2014 at 11:46 AM, Domenic Denicola < domenic at domenicdenicola.com> wrote:

From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of Dmitry Soshnikov

Am I still missing something?

Yes.

var uint16s = new Uint16Array([258]);
var uint8s = Uint8Array.from(uint16s, x => x / 2);
console.log(uint8s); // [129]
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.

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

# Dmitry Soshnikov (11 years ago)

On Tue, Oct 7, 2014 at 11:56 AM, Claude Pache <claude.pache at gmail.com>

wrote:

Le 7 oct. 2014 à 20:36, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> a écrit :

And other things are better be written:

<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

# Dmitry Soshnikov (11 years ago)

On Tue, Oct 7, 2014 at 11:59 AM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:

On Tue, Oct 7, 2014 at 11:56 AM, Claude Pache <claude.pache at gmail.com> wrote:

Le 7 oct. 2014 à 20:36, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> a écrit :

And other things are better be written:

<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)));

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

# Dmitry Soshnikov (11 years ago)

On Tue, Oct 7, 2014 at 12:01 PM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:

On Tue, Oct 7, 2014 at 11:59 AM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:

On Tue, Oct 7, 2014 at 11:56 AM, Claude Pache <claude.pache at gmail.com> wrote:

Le 7 oct. 2014 à 20:36, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> a écrit :

And other things are better be written:

<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)));

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).

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

# Dmitry Soshnikov (11 years ago)

On Tue, Oct 7, 2014 at 11:46 AM, Domenic Denicola < domenic at domenicdenicola.com> wrote:

From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of Dmitry Soshnikov

Am I still missing something?

Yes.

var uint16s = new Uint16Array([258]);
var uint8s = Uint8Array.from(uint16s, x => x / 2);
console.log(uint8s); // [129]
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

# Rick Waldron (11 years ago)

On Tue, Oct 7, 2014 at 3:01 PM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com

wrote:

On Tue, Oct 7, 2014 at 11:59 AM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:

On Tue, Oct 7, 2014 at 11:56 AM, Claude Pache <claude.pache at gmail.com> wrote:

Le 7 oct. 2014 à 20:36, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> a écrit :

And other things are better be written:

<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)));

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?

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);

# Dmitry Soshnikov (11 years ago)

On Tue, Oct 7, 2014 at 12:22 PM, Rick Waldron <waldron.rick at gmail.com>

wrote:

On Tue, Oct 7, 2014 at 3:01 PM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:

On Tue, Oct 7, 2014 at 11:59 AM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:

On Tue, Oct 7, 2014 at 11:56 AM, Claude Pache <claude.pache at gmail.com> wrote:

Le 7 oct. 2014 à 20:36, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> a écrit :

And other things are better be written:

<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)));

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?

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);

Exactly. And this is what I mentioned at the beginning: the performance reasons shouldn't (never) overweight in "good API design" topics.

Dmitry

# Dmitry Soshnikov (11 years ago)

On Tue, Oct 7, 2014 at 12:25 PM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:

On Tue, Oct 7, 2014 at 12:22 PM, Rick Waldron <waldron.rick at gmail.com> wrote:

On Tue, Oct 7, 2014 at 3:01 PM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:

On Tue, Oct 7, 2014 at 11:59 AM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:

On Tue, Oct 7, 2014 at 11:56 AM, Claude Pache <claude.pache at gmail.com> wrote:

Le 7 oct. 2014 à 20:36, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> a écrit :

And other things are better be written:

<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)));

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?

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);

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

# Dmitry Soshnikov (11 years ago)

On Tue, Oct 7, 2014 at 12:27 PM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:

On Tue, Oct 7, 2014 at 12:25 PM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:

On Tue, Oct 7, 2014 at 12:22 PM, Rick Waldron <waldron.rick at gmail.com>

wrote:

On Tue, Oct 7, 2014 at 3:01 PM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:

On Tue, Oct 7, 2014 at 11:59 AM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:

On Tue, Oct 7, 2014 at 11:56 AM, Claude Pache <claude.pache at gmail.com> wrote:

Le 7 oct. 2014 à 20:36, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> a écrit :

And other things are better be written:

<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)));

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?

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);

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

# Tab Atkins Jr. (11 years ago)

On Tue, Oct 7, 2014 at 12:32 PM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> wrote:

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.

# Dmitry Soshnikov (11 years ago)

On Tue, Oct 7, 2014 at 12:50 PM, Tab Atkins Jr. <jackalmage at gmail.com>

wrote:

On Tue, Oct 7, 2014 at 12:32 PM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> wrote:

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

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

# Claude Pache (11 years ago)

Le 7 oct. 2014 à 21:32, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> a écrit :

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).

# Dmitry Soshnikov (11 years ago)

On Tue, Oct 7, 2014 at 1:20 PM, Claude Pache <claude.pache at gmail.com> wrote:

Le 7 oct. 2014 à 21:32, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> a écrit :

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

# Bergi (11 years ago)

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).

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 (11 years ago)

On Tue, Oct 7, 2014 at 1:45 PM, Bergi <a.d.bergi at web.de> wrote:

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

# Tab Atkins Jr. (11 years ago)

On Tue, Oct 7, 2014 at 2:11 PM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> wrote:

On Tue, Oct 7, 2014 at 1:45 PM, Bergi <a.d.bergi at web.de> wrote:

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:

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.

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).

# Dmitry Soshnikov (11 years ago)

On Tue, Oct 7, 2014 at 2:20 PM, Tab Atkins Jr. <jackalmage at gmail.com> wrote:

On Tue, Oct 7, 2014 at 2:11 PM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> wrote:

On Tue, Oct 7, 2014 at 1:45 PM, Bergi <a.d.bergi at web.de> wrote:

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:

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.

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

# Tab Atkins Jr. (11 years ago)

On Tue, Oct 7, 2014 at 2:26 PM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> wrote:

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 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.

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.

# Dmitry Soshnikov (11 years ago)

On Tue, Oct 7, 2014 at 2:35 PM, Tab Atkins Jr. <jackalmage at gmail.com> wrote:

On Tue, Oct 7, 2014 at 2:26 PM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> wrote:

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 < 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.

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 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

# Claude Pache (11 years ago)

Le 7 oct. 2014 à 23:43, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> a écrit :

On Tue, Oct 7, 2014 at 2:35 PM, Tab Atkins Jr. <jackalmage at gmail.com> wrote: On Tue, Oct 7, 2014 at 2:26 PM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> wrote:

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 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.

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 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... :

# Dmitry Soshnikov (11 years ago)

On Tue, Oct 7, 2014 at 4:08 PM, Claude Pache <claude.pache at gmail.com> wrote:

Le 7 oct. 2014 à 23:43, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> a écrit :

On Tue, Oct 7, 2014 at 2:35 PM, Tab Atkins Jr. <jackalmage at gmail.com> wrote:

On Tue, Oct 7, 2014 at 2:26 PM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> wrote:

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 < 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.

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 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: twitter.com/DmitrySoshnikov/status/519964146637737986

The mapping function from Array.from considers holes (from the new TC39 "policy"), but Array#map does not.

I guess this doc on Array.from from MDN [1] should be fixed then:

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] developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from

Dmitry

# Dmitry Soshnikov (11 years ago)

On Wed, Oct 8, 2014 at 2:42 PM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com

wrote:

On Tue, Oct 7, 2014 at 4:08 PM, Claude Pache <claude.pache at gmail.com> wrote:

Le 7 oct. 2014 à 23:43, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> a écrit :

On Tue, Oct 7, 2014 at 2:35 PM, Tab Atkins Jr. <jackalmage at gmail.com> wrote:

On Tue, Oct 7, 2014 at 2:26 PM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> wrote:

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 < 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.

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 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: twitter.com/DmitrySoshnikov/status/519964146637737986

The mapping function from Array.from considers holes (from the new TC39 "policy"), but Array#map does not.

I guess this doc on Array.from from MDN [1] should be fixed then:

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] 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: gyazo.com/4709305f3bde1c8ce0b02d2071a99e7f

Dmitry

# Dmitry Soshnikov (11 years ago)

On Wed, Oct 8, 2014 at 2:47 PM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com

wrote:

On Wed, Oct 8, 2014 at 2:42 PM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:

On Tue, Oct 7, 2014 at 4:08 PM, Claude Pache <claude.pache at gmail.com> wrote:

Le 7 oct. 2014 à 23:43, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> a écrit :

On Tue, Oct 7, 2014 at 2:35 PM, Tab Atkins Jr. <jackalmage at gmail.com> wrote:

On Tue, Oct 7, 2014 at 2:26 PM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> wrote:

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 < 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.

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 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: twitter.com/DmitrySoshnikov/status/519964146637737986

The mapping function from Array.from considers holes (from the new TC39 "policy"), but Array#map does not.

I guess this doc on Array.from from MDN [1] should be fixed then:

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] 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: 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