About Array.of()
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.
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.
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.
Array.of
is unambiguous with the current ES specification
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.
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
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
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 ;)
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
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.
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.
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");
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.
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.
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
.
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).
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"!
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
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.
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>:
Array.fromElements is solid, especially considering how rarely this will be used, especially given that it competes in ES6 code with ...x => [...x]
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)!
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.
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?
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])
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
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...
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?
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.
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.
-
Array.of
sounds expressive only for native speakers. Non native programmers will have no idea aboutArray.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 searcharray.of
in github, you will see manyarray of int
array of byte
array of strings
array of Book
orarray of Point
... in code or comments. -
In fact such expressive is MEANINGLESS because we will never write
var a = Array.of(1, 2, 3)
instead ofvar 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 DOMElements
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.
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).
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 ofvar 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
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? :)
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.
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
...
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 useArray.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