About Array.of()

# Shijun He (13 years ago)

I don't think Array.of() is useful, just stick on array literal seems enough:

var a = [1,2,3]
var a1 = [3]

Why we need this:

var a = Array.of(1,2,3)
var a1 = Array.of(3)

Is there any special benefit I missed?

And there is another reason why I don't like Array.of(), myself write a small library which use Array.of(type) to get a "strong-typed" array:

var StringArray = Array.of(String)
var a = StringArray.from(['a', 1, true]) // ['a', '1', 'true']
a.push('string')  // ['a', '1', 'true', 'string']
a.push(100) // throws error

And Function.of():

var sqrt = Function.of(Number).from(Math.sqrt)
sqrt(9) // 3
sqrt('9') // error
sqrt(9, 'unwanted') // error
# Rick Waldron (13 years ago)

Thanks for the feedback, allow me to explain the rationale for Array.of:

One of the main goals of ES6 is to become a better language for library writers and code generators.

For compilation targets, ES/JS can't assume that implementations will always know what its factories are expected to construct:

Imagine the following piece of code is used in a VM (think Dart->JS, LLJS->JS)

var o = (function( construct, ...rest ) {
  return new construct( rest );
})( factory [, variable arity args] );

If factory is Array and only one numeric arg is given, inline like this:

var o = (function( construct, ...rest ) {
  return new construct( rest );
})( Array, 10 );

The result of o will be an array with 10 empty indexes, as if it were called like:

new Array(10)

If you replace that by using Array.of(), you avoid this "gotcha"

More comments inline...

On Sunday, August 26, 2012 at 5:53 AM, Shijun He wrote:

Is there any special benefit I missed?

Explained above :)

And there is another reason why I don't like Array.of() , myself write a small library which use Array.of(type) to get a "strong-typed" array:

I'd argue that if code is extending ES built-ins with non-standard properties, it accepts the risk that one day it may be in conflict.

# Brendan Eich (13 years ago)

Rick Waldron wrote:

If you replace that by using Array.of(), you avoid this "gotcha"

That's right -- Array.of is an alternative constructor to use in preference to Array, on account of Array's heinous special-case for the one-numeric-argument case.

# Shijun He (13 years ago)

On Sun, Aug 26, 2012 at 7:14 PM, Rick Waldron <waldron.rick at gmail.com> wrote:

If you replace that by using Array.of(), you avoid this "gotcha"

So you still need some code like:

if (constructor === Array) return Array.of(rest)
else return new construct(rest)

And of cause we can write it as:

if (constructor === Array) return [rest]

Or, maybe you mean we should write

o = ....(Array.of, 10)
instead of
o = ....(Array, 10)

But is this case strong enough to add such a simple function to standard library?

I'd argue that if code is extending ES built-ins with non-standard properties, it accepts the risk that one day it may be in conflict.

And if it should be added, could you choose a better name? Array.isArray is good example which will not introduce any ambiguity. But Array.of is not. Maybe Array.new is a good name.

# Rick Waldron (13 years ago)

Array.of is unambiguous with the current ES specification

# Brendan Eich (13 years ago)

Array.new is ok too, though -- no problem with a reserved identifier as a property name. It's darn nice for Rubyists.

OTOH Array.of matches the preposition pattern used in Array.from. But I don't think this trumps Array.new. Cc'ing Dave for his thoughts.

# Rick Waldron (13 years ago)

Nor do I, but I think it poses a problem for polyfilling (which is not a silver bullet).

+1 Array.new, but I still think Array.of sounds, feels and looks nicer

# Matthew Robb (13 years ago)

I agree with Rick on the general feeling with Array.of

If arguing ambiguity I would argue a better method name for type guarded arrays would be Array.ofType

# Shijun He (13 years ago)

See the screenshots for the "array of" search suggestion in search engine. As a non-English native speaker, I'd like to say the search suggestion of "array of" in non-english languages seems most come from the programmers' input, so it shows how worldwide programmers think what "array of" means ;)

# Matthew Robb (13 years ago)

You are absolutely correct... That is if you are creating method names that include the type

Array.ofStrings() is certainly more clear than Array.ofType(String) but it has it's obvious negatives. We already have a concept in the language which is typeof so could even go with Array.typeOf(String)

I'll also comment that I sort of dislike the sound of Array.new() shrug

# Rick Waldron (13 years ago)

I don't think that screenshots of search suggestions for a language feature that hasn't even been published is valid argument in this discussion.

I'd also argue that these results support the current Array.of definition, eg.

"I need to make an array of strings":

Array.of( "A", "B", "C", "D" );

...Which returns an array of strings. Any example works, Array.of( things, ... ) nicely describes what the function can be expected to do. As I noted earlier, I'm not opposed to Array.new(), but I maintain the position that it reads like backwards computer speak.

# Brendan Eich (13 years ago)

Just FTR, no one is proposing type guarded variants. Maybe they'll be wanted later -- so the alterna-constructor method(s) can be named then.

For now, Array.new is polyfill-able on pre-ES5 implementations if you are willing to write Array['new'] all over. That is a drag, though.

# Kevin Smith (13 years ago)

Isn't there a name that we already use for alternative constructors: create?

let object = Object.create(null);
let array = Array.create("A", "B", "C");
# Brendan Eich (13 years ago)

If only create weren't used for Object.create, which takes a pdmap as second parameter. That is a complicated beast, with the wrong defaults for writable configurable and arguably enumerable.

The Ruby precedent for Array.new appeals to me (and I'm not a Rubyist).

I could live with Array.of but even ignoring search-engine usability, using a preposition for a constructor name, rather than a verb or a verb'ed adjective, counts against it a tiny bit IMHO.

# Rick Waldron (13 years ago)

Regardless of its repositioning on the right as a property, I would intuitively expect "new" to behave the same way it would as its operator equivalent (for all constructors, not just Array). By no means do I wish to be combative, but I feel strongly that repurposing the same word is user hostile.

# Shijun He (13 years ago)

On Tue, Aug 28, 2012 at 1:55 AM, Rick Waldron <waldron.rick at gmail.com> wrote:

I don't think that screenshots of search suggestions for a language feature that hasn't even been published is valid argument in this discussion.

I'd also argue that these results support the current Array.of definition, eg.

"I need to make an array of strings":

Array.of( "A", "B", "C", "D" );

...Which returns an array of strings. Any example works, Array.of( things

You may miss that, only suggestions in English version of Bing have many "-s". That means, most non-English (At least Chinese as my screenshots) programmers won't think like that.

BTW, my Class.of(Type) choice come from VB.NET which use Class (of Type) to denote generics.

... ) nicely describes what the function can be expected to do. As I noted earlier, I'm not opposed to Array.new(), but I maintain the position that it reads like backwards computer speak.

Maybe it like computer speak for native English speakers, but for me and many programmers from non-English world, Array.new is much more intuitive than Array.of.

# Shijun He (13 years ago)

On Tue, Aug 28, 2012 at 4:38 AM, Rick Waldron <waldron.rick at gmail.com> wrote:

Regardless of its repositioning on the right as a property, I would intuitively expect "new" to behave the same way it would as its operator equivalent (for all constructors, not just Array). By no means do I wish to

I agree you 'new' should match constructor, except Array. Array constructor is broken (that's why we need Array.of/new/create whatever) and NO ONE really use Array constructor at all (programmers are educated to use literal initializer instead).

# Brendan Eich (13 years ago)

Too true.

Rick, it's important not to make a false idol out of precedent. When people want an Array constructor, they don't think "especially one that treats the case where it is called with a single argument of number type as a request to make an array with that many holes"!

# Rick Waldron (13 years ago)

On Mon, Aug 27, 2012 at 9:41 PM, Brendan Eich <brendan at mozilla.org> wrote:

Rick, it's important not to make a false idol out of precedent.

You're absolutely right, sometimes my intentions to speak for the wider population act as blinders.

When people want an Array constructor, they don't think "especially one that treats the case where it is called with a single argument of number type as a request to make an array with that many holes"!

You got me there :P

# 程劭非 (13 years ago)

Yes, as a developer (but not English native speaker), I really feel uncomfortable with the name “of”.

Considering we already have

  • Object.create
  • String.fromCharCode

To keep align with them, I belive “create” or “fromElements” might be better choices.

# 程劭非 (13 years ago)

Yes, as a developer (but not English native speaker), I really feel uncomfortable with the name “of”.

Considering we already have Object.create String.fromCharCode

To keep align with them, I belive “create” or “fromElements” might be better choices.

2012/8/27 Shijun He <hax.sfo at gmail.com>:

# Domenic Denicola (13 years ago)

Array.fromElements is solid, especially considering how rarely this will be used, especially given that it competes in ES6 code with ...x => [...x]

# Mikael Lindsten (13 years ago)

I agree with Domenic, Array.fromElements would be a good name (though I have no problem with Array.of). Just don't go with Array.new (I agree with Rick here, it should match the constructor - Array should be no exception, broken constructor or not)!

# Maciej Stachowiak (13 years ago)

On Aug 26, 2012, at 4:30 PM, Brendan Eich <brendan at mozilla.com> wrote:

Array.new is ok too, though -- no problem with a reserved identifier as a property name. It's darn nice for Rubyists.

Another possibility is Array.create, following the pattern of Object.create. "of" seems like a funky name for a constructor, to my taste.

# Jussi Kalliokoski (13 years ago)

True, but I'd rather see Array.create as a fix for the "one argument Array constructor", i.e. creating an array of the specified length, without holes. For example:

Array.create = function (length) {
  if (length === 1) return [undefined]

  return Array.apply(null, Array(length))
}

There's been some discussion of that earlier, actually 1.

My 2 cents goes to Array.fromElements, conveys very well what it does.

However, I'm still not quite sure what the use case is for this. For code generation, if you know how many elements there are and what they are enough to put them in the Array.of(...,...,...) call, why not just use [...,...,...]? Unless it's supposed to be used for converting array-likes to arrays, where I really don't think this is the best function signature. For the dart example, why not just use [] and you avoid the gotcha?

# Axel Rauschmayer (13 years ago)

However, I'm still not quite sure what the use case is for this. For code generation, if you know how many elements there are and what they are enough to put them in the Array.of(...,...,...) call, why not just use [...,...,...]? Unless it's supposed to be used for converting array-likes to arrays, where I really don't think this is the best function signature. For the dart example, why not just use [] and you avoid the gotcha?

map and map-like scenarios are another use case:

[1,2,3].map(Array.of)  // [[1], [2], [3]]

But, as Domenic mentions, it does indeed compete with:

[1,2,3].map(...x => [...x])
# Jussi Kalliokoski (13 years ago)

Yeah, and in that case (making every element of an array an array), actually:

[1,2,3].map(x => [x])

Which is even shorter.

I really have a hard time seeing any value in having this feature. All the problems it's supposed to solve (at least the ones presented here) already have better solutions. :D

# Shijun He (11 years ago)

This is an old thread which I like to mention again. The proposal is change the method name from Array.of() to Array.fromElements() to make it clear especially for non-English native programmers.

It seems the thread is totally ignored...

# Benjamin (Inglor) Gruenbaum (11 years ago)

Array.of sounds a lot more expressive than .fromElements to me.

Optimally I'd like the array constructor to just accept a collection and convert it to an array but that's not going to happen. Would you mind explaining the issue here for non native English speakers?

# Rick Waldron (11 years ago)

On Wed, Dec 18, 2013 at 7:33 AM, Benjamin (Inglor) Gruenbaum <inglor at gmail.com> wrote:

Array.of sounds a lot more expressive than .fromElements to me.

Agreed.

Additionally, fromElements will also be confusing when the new DOM Elements API arrives: dom.spec.whatwg.org/#elements

Optimally I'd like the array constructor to just accept a collection and convert it to an array but that's not going to happen. Would you mind explaining the issue here for non native English speakers?

The specification reads:

Array.of(...items)

Which, when said out loud is:

"Array of items"

I don't know how much clearer that can get. Bikeshedding the name of an API at this stage in ES6's progress is not a valuable use of anyone's time.

# Shijun He (11 years ago)

On Thu, Dec 19, 2013 at 12:08 AM, Rick Waldron <waldron.rick at gmail.com>wrote:

Array.of sounds a lot more expressive than .fromElements to me.

Agreed.

  1. Array.of sounds expressive only for native speakers. Non native programmers will have no idea about Array.of method, because they never seen such named method with such usage in any codes of any programming languages before (at least I never seen), if you search array.of in github, you will see many array of int array of byte array of strings array of Book or array of Point... in code or comments.

  2. In fact such expressive is MEANINGLESS because we will never write var a = Array.of(1, 2, 3) instead of var a = [1, 2, 3]

The only valid use case of Array.of is high-order function.

So what's the readability of foo(bar, array.of) ?

I just find that Dave Herman already pointed out this problem in the original thread:

That said, the "readability" story you and I tweeted about is not so compelling given that, in the first-order usage pattern an array-literal is strictly more readable. So a longer name like Array.fromElements or something might be okay.

Interesting that Dave (native speaker) and 程劭非(a non native speaker which suggest this name in this thread) both choose fromElements in the first place.

Additionally, fromElements will also be confusing when the new DOM Elements API arrives: dom.spec.whatwg.org/#elements

Well, even it's confusing it's still better than of for the use case, and some other alternatives:

Array.fromItems // fromXXX has another benifit that alternative constructors (String.fromCharCode, Array.from) all begin with `from`
Array.fromList
Array.fromArguments
Array.newArray
Array.makeArray
Array.theFixedConstructorWithoutGotchas

I like the last one ;) what about you?

The specification reads:

Array.of(...items)

Which, when said out loud is:

"Array of items"

Even Array.ofItems is better than Array.of for the only use case: foo(bar, Array.ofItems)

I don't know how much clearer that can get. Bikeshedding the name of an API at this stage in ES6's progress is not a valuable use of anyone's time.

Come on, there are only two things in Computer Science: cache invalidation and naming things.

And if we don't fix bad names in this stage, we will lose the chance for ever.

# Benjamin (Inglor) Gruenbaum (11 years ago)

Array.of sounds expressive only for native speakers.

English is not my first language and it sounded expressive to me. I've asked 5 random friends that code and they all said it sounded fine to them. While that's not real evidence, it still shows that the "only" doesn't hold here.

The only valid use case of Array.of is high-order function.

No it's not. The main use case I see is converting array like structures (like NodeLists) to arrays without having to do that dirty Array.prototype.splice.call call:

Array.of(document.querySelectorAll(".bar"))

Higher order functions are a real use case but for sure not the only one. I completely agree with Rick that fromElements is confusing for the API especially that creating an array out of actual DOM Elements is a use case and it implies that it only works for that use case.

Like I said, the optimal thing would have been to be able to do Array(arrayLike) and have it "just work" and create a new array from that collection (like collections tend to do in Java, C#, Python etc) but it's too late for that. That breaks ES (Array([1]) returns [[1]]). Array.of seems very close of that, you make an array of the items passed. The fact it's a static method makes it very clear that that's what it does IMO (although personally I'd favor putting it somewhere else).

# Allen Wirfs-Brock (11 years ago)

On Dec 18, 2013, at 11:01 AM, Shijun He wrote:

2. In fact such expressive is MEANINGLESS because we will never write var a = Array.of(1, 2, 3) instead of var a = [1, 2, 3]

Note that 'of' works to create instances of subclasses or Array (and typed arrays) while array literals do not.

class MyArray extends Array { }

var ma = MyArray.of(1,2,3);

console.log(ma instanceof MyArray);  //true
# Shijun He (11 years ago)

On Thu, Dec 19, 2013 at 4:04 AM, Benjamin (Inglor) Gruenbaum <inglor at gmail.com> wrote:

English is not my first language and it sounded expressive to me. I've asked 5 random friends that code and they all said it sounded fine to them. While that's not real evidence, it still shows that the "only" doesn't hold here.

Could you ask what's your and your friend's native language?

No it's not. The main use case I see is converting array like structures (like NodeLists) to arrays without having to do that dirty Array.prototype.splice.call call:

Array.of(document.querySelectorAll(".bar"))

Oops, it should be Array.from(document.querySelectorAll('.bar')).

Higher order functions are a real use case but for sure not the only one. I completely agree with Rick that fromElements is confusing for the API especially that creating an array out of actual DOM Elements is a use case and it implies that it only works for that use case.

I already give some alternatives. Just choose what you like.

Like I said, the optimal thing would have been to be able to do Array(arrayLike) and have it "just work" and create a new array from that collection (like collections tend to do in Java, C#, Python etc) but it's too late for that. That breaks ES (Array([1]) returns [[1]]). Array.of seems very close of that, you make an array of the items passed. The fact it's a static method makes it very clear that that's what it does IMO (although personally I'd favor putting it somewhere else).

So could I use your misunderstanding of Array.of/from as a example that Array.of is a bad name? :)

# Shijun He (11 years ago)

On Thu, Dec 19, 2013 at 4:37 AM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:

Note that 'of' works to create instances of subclasses or Array (and typed arrays) while array literals do not.

var ma = new MyArray(1, 2, 3)

still work.

If we want to avoid the constructor, we can :

var ma = MyArray.from([1, 2, 3])

or just fix the constructor --- if the behavior of default constructor is confusing why not fix it? For the built-in Array we can not, but you already extend it here!

class MyArray extends Array {
  constructor(...a) { this.push(...a) }
}

So I still think only high-order usage for built-in Array is a real use case.

# Claude Pache (11 years ago)

Well, even it's confusing it's still better than of for the use case, and some other alternatives:

Array.fromItems // fromXXX has another benifit that alternative constructors (String.fromCharCode, Array.from) all begin with `from`
Array.fromList
Array.fromArguments
Array.newArray
Array.makeArray
Array.theFixedConstructorWithoutGotchas

I like the last one ;) what about you?

Of/from the alternatives proposed, I find Array.fromArguments compelling, because it is self-descriptive once you know what does Array.from:

Array.fromArguments = function() { return Array.from(arguments) }

Remarkably, Array.fromElements sounds particularly bad to my ears, because it seems to be a synonym of Array.from when applied to an array. ("Array from [the] elements [of] ...")

Personally, I'd not thought that Array.of would be a problem, but apparently, since even people that are fine with that name tend to mingle it with Array.from...