Uninteresting parameters

# Sean Eagan (13 years ago)

Most aspects of destructuring are supported in parameter lists:

  • rest parameters
  • destructuring of individual parameters

However, there is at least one aspect which is not, which is uninteresting parameters :

[x, , z] = arr;

which for parameter lists would look like:

function(x, , z) {...}

This could be useful when you are a defining a callback which needs to match a certain signature, but you only care about a certain subset of the arguments not at the beginning. For example:

function evens(arr) { arr.filter(function(,index) {return index % 2}); }

However, I admit it can look strange especially when the uninteresting parameter is at the beginning as in the above example.

Thanks, Sean Eagan

# Xavier MONTILLET (13 years ago)

Normally, you use an object for optional arguments.

And there is no good reason not to since you don't care about the order of the arguments.

Sent from my smartphone.

# Dominic Cooney (13 years ago)

Since, as I understand it, these are evaluated as successive assignment to the successive lvalues the author could adopt a practice like repeatedly assigning to the variable _.

I am not sure that will work in const statements, though.

Dominic

# Sean Eagan (13 years ago)

On Mon, Sep 26, 2011 at 4:47 PM, Xavier MONTILLET <xavierm02.net at gmail.com> wrote:

Normally, you use an object for optional arguments.

This is probably the most common case in practice, however...

And there is no good reason not to since you don't care about the order of the arguments.

There are two good reasons:

  • it's more concise since you don't have to prefix each argument access with the the object argument name + ".", however, destructuring now helps here
  • library author does not need to introduce argument names, the callback author can use whatever names they want, such as an abbreviations for example

Also, there are existing and future in-language APIs which receive multiple argument callbacks, for example:

  • Array.prototype methods
  • Proxy traps

Thanks, Sean Eagan

# Brendan Eich (13 years ago)

On Sep 27, 2011, at 6:11 AM, Sean Eagan wrote:

On Mon, Sep 26, 2011 at 4:47 PM, Xavier MONTILLET <xavierm02.net at gmail.com> wrote:

Normally, you use an object for optional arguments.

This is probably the most common case in practice, however...

And there is no good reason not to since you don't care about the order of the arguments.

There are two good reasons:

  • it's more concise since you don't have to prefix each argument access with the the object argument name + ".", however, destructuring now helps here
  • library author does not need to introduce argument names, the callback author can use whatever names they want, such as an abbreviations for example

Also, there are existing and future in-language APIs which receive multiple argument callbacks, for example:

  • Array.prototype methods
  • Proxy traps

Trailing formal parameters do not need to be declared if not used in JS.

Holes in parameter lists have some uses as you point out, but they're rare enough that I don't think we should add parameter list holes.

# Sean Eagan (13 years ago)

On Tue, Sep 27, 2011 at 2:43 PM, Brendan Eich <brendan at mozilla.com> wrote:

On Sep 27, 2011, at 6:11 AM, Sean Eagan wrote:

On Mon, Sep 26, 2011 at 4:47 PM, Xavier MONTILLET <xavierm02.net at gmail.com> wrote:

Normally, you use an object for optional arguments.

This is probably the most common case in practice, however...

And there is no good reason not to since you don't care about the order of the arguments.

There are two good reasons:

  • it's more concise since you don't have to prefix each argument access with the the object argument name + ".", however, destructuring now helps here
  • library author does not need to introduce argument names, the callback author can use whatever names they want, such as an abbreviations for example

Also, there are existing and future in-language APIs which receive multiple argument callbacks, for example:

  • Array.prototype methods
  • Proxy traps

Trailing formal parameters do not need to be declared if not used in JS.

Holes in parameter lists have some uses as you point out, but they're rare enough that I don't think we should add parameter list holes.

I agree, but it seems like holes in parameter lists would be no more rare than holes in destructuring lists...

[a, , c] = arr;

...so it seems strange to add it to one but not the other.

Thanks, Sean Eagan

# Brendan Eich (13 years ago)

On Sep 27, 2011, at 12:50 PM, Sean Eagan wrote:

I agree, but it seems like holes in parameter lists would be no more rare than holes in destructuring lists...

[a, , c] = arr;

Could be.

...so it seems strange to add it to one but not the other.

Destructuring uses the same grammar as "structuring", i.e. ObjectLiteral and ArrayLiteral. We can and are making post-parse ("Supplemental Syntax") restrictions, so we could forbid holes, but it's more work.

Contrast to parameter lists where adding holes is more work.

Is more work for the spec the good to optimize? For such truly marginal cases, I think so.

# Dean Landolt (13 years ago)

On Tue, Sep 27, 2011 at 4:04 PM, Brendan Eich <brendan at mozilla.com> wrote:

On Sep 27, 2011, at 12:50 PM, Sean Eagan wrote:

I agree, but it seems like holes in parameter lists would be no more rare than holes in destructuring lists...

[a, , c] = arr;

Could be.

...so it seems strange to add it to one but not the other.

Destructuring uses the same grammar as "structuring", i.e. ObjectLiteral and ArrayLiteral. We can and are making post-parse ("Supplemental Syntax") restrictions, so we could forbid holes, but it's more work.

Contrast to parameter lists where adding holes is more work.

Is more work for the spec the good to optimize? For such truly marginal cases, I think so.

Out of curiosity is there any reason to keep holes the holes around in ObjectLiteral and ArrayLiteral? Is there a real usecase (other than rare and trivial minification wins)? Sure, it would be a breaking syntax change but statically detectable and correctable. And it would wipe out a source of bugs rather than doubling down.

# Brendan Eich (13 years ago)

On Sep 27, 2011, at 1:21 PM, Dean Landolt wrote:

Out of curiosity is there any reason to keep holes the holes around in ObjectLiteral and ArrayLiteral?

No holes in ObjectLiteral.

It's true for ES6, opt-in only, we could change ArrayLiteral to remove holes. This would make early errors for code migrating into ES6 that uses holes, and for authors writing fresh ES6 programs who use holes.

(Note well that [1,] is an array of length 1, no holes.)

Is there a real usecase (other than rare and trivial minification wins)? Sure, it would be a breaking syntax change but statically detectable and correctable. And it would wipe out a source of bugs rather than doubling down.

What bugs have you seen due to holes in literas? I've never seen or heard of any such bugs. The possibility of holes exists without literal syntax support, due to the ability to add elements to an array by assignment to non-contiguous indexes, delete elements, and set length.

I don't see how to get rid of holes created via these means without making runtime-only, not early, errors -- and that's too big a migration tax. It's a source of new bugs that we could avoid by not trying to ban holes.

So, if we still have holes, is it really worth getting rid of ArrayLiteral support for them? I think not.

BTW, I proposed, as part of Harmony of My Dreams, tuples: strawman:tuples -- no holes, immutable, sane enumeration. Not in Harmony yet.

# Dean Landolt (13 years ago)

On Tue, Sep 27, 2011 at 4:57 PM, Brendan Eich <brendan at mozilla.com> wrote:

On Sep 27, 2011, at 1:21 PM, Dean Landolt wrote:

Out of curiosity is there any reason to keep holes the holes around in ObjectLiteral and ArrayLiteral?

No holes in ObjectLiteral.

Apologies -- I was thinking of the trailing comma, but that's not at issue.

It's true for ES6, opt-in only, we could change ArrayLiteral to remove holes. This would make early errors for code migrating into ES6 that uses holes, and for authors writing fresh ES6 programs who use holes.

(Note well that [1,] is an array of length 1, no holes.)

Is there a real usecase (other than rare and trivial minification wins)? Sure, it would be a breaking syntax change but statically detectable and correctable. And it would wipe out a source of bugs rather than doubling down.

What bugs have you seen due to holes in literas?

Copy/paste errors, mainly. I'd think the same rationale to justify the trailing comma applies against comma holes in array literals.

I've never seen or heard of any such bugs.

I've made this mistake more than once. This kind of bug tends to fail fast so it's not as easy to slip into production, but it's still a runtime error. What's worse, the problem is exacerbated by the fact that tools that lean on Array.prototype.forEach hide the hole, while those that use for(;;) treat it as undefined. I understand that this is a problem with holes in general, and not with ArrayLiteral syntax in particular, but try a console.log on a holy array in, for instance, node and then chrome -- you'll get two VERY different-looking results. The way that console.log in node completely papers over array holes, compounded by the popularity of the comma-first style in that community (which makes a double-comma harder to spot), could be a pretty nasty trap to fall into, even for a js veteran.

The possibility of holes exists without literal syntax support, due to the ability to add elements to an array by assignment to non-contiguous indexes, delete elements, and set length.

Sure, and I'm not arguing for eliminating holes altogether...

I don't see how to get rid of holes created via these means without making runtime-only, not early, errors -- and that's too big a migration tax. It's a source of new bugs that we could avoid by not trying to ban holes.

So, if we still have holes, is it really worth getting rid of ArrayLiteral support for them? I think not.

But are they of any real use for ArrayLiterals? IMHO a hole in a small array (i.e. an ArrayLiteral) is almost always a mistake, and when it's not there's imperative syntax to fall back on. So if there's no good use for it, why enshrine a bad practice with a declarative syntax? The migration tax would trivial, as you alluded.

BTW, I proposed, as part of Harmony of My Dreams, tuples: strawman:tuples -- no holes, immutable, sane enumeration. Not in Harmony yet.

Yeah, those would be nice -- almost as awesome as the records you proposed :)

# Brendan Eich (13 years ago)

On Sep 27, 2011, at 4:02 PM, Dean Landolt wrote:

On Tue, Sep 27, 2011 at 4:57 PM, Brendan Eich <brendan at mozilla.com> wrote: On Sep 27, 2011, at 1:21 PM, Dean Landolt wrote:

Out of curiosity is there any reason to keep holes the holes around in ObjectLiteral and ArrayLiteral?

No holes in ObjectLiteral.

Apologies -- I was thinking of the trailing comma, but that's not at issue.

Right, one (1) comma at end of either object or array literal is a terminator, for uniform maintenance when appending vs. inserting. Very big deal for those of us burned by ANSI C banning trailing single comma in C enum!

What bugs have you seen due to holes in literas?

Copy/paste errors, mainly. I'd think the same rationale to justify the trailing comma applies against comma holes in array literals.

Hmm, I think I see what you mean, but the hole case is different enough and anyway it has been in the language for 12 years.

I've made this mistake more than once. This kind of bug tends to fail fast so it's not as easy to slip into production, but it's still a runtime error.

Ouch. And apologies.

What's worse, the problem is exacerbated by the fact that tools that lean on Array.prototype.forEach hide the hole, while those that use for(;;) treat it as undefined.

That is a pain. I've heard independently that some people want forEach etc. to fill holes. Can you confirm?

I understand that this is a problem with holes in general, and not with ArrayLiteral syntax in particular, but try a console.log on a holy array in, for instance, node and then chrome -- you'll get two VERY different-looking results. The way that console.log in node completely papers over array holes, compounded by the popularity of the comma-first style in that community (which makes a double-comma harder to spot),

I find comma first just ugly on aesthetic grounds.

could be a pretty nasty trap to fall into, even for a js veteran.

Adjacent comma does scream HOLE to me, but that's just me.

So, if we still have holes, is it really worth getting rid of ArrayLiteral support for them? I think not.

But are they of any real use for ArrayLiterals? IMHO a hole in a small array (i.e. an ArrayLiteral) is almost always a mistake,

Or a testcase for the otherwise unwanted feature:

codesearch.google.com/#search/&q=", ," lang:^javascript$&type=cs

Some of those look intentional, and non-testy, though.

# Dean Landolt (13 years ago)

On Wed, Sep 28, 2011 at 12:52 AM, Brendan Eich <brendan at mozilla.com> wrote:

On Sep 27, 2011, at 4:02 PM, Dean Landolt wrote:

On Tue, Sep 27, 2011 at 4:57 PM, Brendan Eich <brendan at mozilla.com> wrote:

On Sep 27, 2011, at 1:21 PM, Dean Landolt wrote:

Out of curiosity is there any reason to keep holes the holes around in ObjectLiteral and ArrayLiteral?

No holes in ObjectLiteral.

Apologies -- I was thinking of the trailing comma, but that's not at issue.

Right, one (1) comma at end of either object or array literal is a terminator, for uniform maintenance when appending vs. inserting. Very big deal for those of us burned by ANSI C banning trailing single comma in C enum!

What bugs have you seen due to holes in literas?

Copy/paste errors, mainly. I'd think the same rationale to justify the trailing comma applies against comma holes in array literals.

Hmm, I think I see what you mean, but the hole case is different enough and anyway it has been in the language for 12 years.

True enough, but wouldn't you say it's still commonly misunderstood?

I've made this mistake more than once. This kind of bug tends to fail fast so it's not as easy to slip into production, but it's still a runtime error.

Ouch. And apologies.

What's worse, the problem is exacerbated by the fact that tools that lean on Array.prototype.forEach hide the hole, while those that use for(;;) treat it as undefined.

That is a pain. I've heard independently that some people want forEach etc. to fill holes. Can you confirm?

It'd be less confusing to the novice, that's for sure. For instance the array extras in at least one lib (dojo) still fill the holes (though I wonder what their plans are around 2.0 when they can break back-compat?).

But there are real perf opportunities on sparse arrays when implemented natively, so they really shouldn't go. Plus, these cases may be tricky to catch with static analysis, so I doubt they even could go. But it'd be nice to take some bullets out of the chamber of this inevitable footgun -- for starters, by making them more explicit.

I understand that this is a problem with holes in general, and not with ArrayLiteral syntax in particular, but try a console.log on a holy array in, for instance, node and then chrome -- you'll get two VERY different-looking results. The way that console.log in node completely papers over array holes, compounded by the popularity of the comma-first style in that community (which makes a double-comma harder to spot),

I find comma first just ugly on aesthetic grounds.

As do I, and I'm still no convert, but I have to say that after toying with it for a bit this is the only substantive criticism I can make of it :)

could be a pretty nasty trap to fall into, even for a js veteran.

Adjacent comma does scream HOLE to me, but that's just me.

Same here, but in comma-first it's not always adjacent:

var middleware = [ context, , csrf , xsite , head , considtional , error ]

You've got to squint a little to see that hole, right?

So, if we still have holes, is it really worth getting rid of ArrayLiteral

support for them? I think not.

But are they of any real use for ArrayLiterals? IMHO a hole in a small array (i.e. an ArrayLiteral) is almost always a mistake,

Or a testcase for the otherwise unwanted feature:

codesearch.google.com/#search/&q=", ," lang:^javascript$&type=cscodesearch.google.com/#search/&q=", ," lang:^javascript$&type=cs

Some of those look intentional, and non-testy, though.

But what does it say that the so many are just explicitly testing this edge case? And an entry from wtfjs, right there on the first page :)

Another wart that springs to mind is the fact that a hole === void 0 but is, in fact, not void 0. I guess technically this is correct -- reifying the index gets you void 0 -- but it's still odd. If there were a way to indexOf for the first hole, for instance, this would at least allow them to be exploited in userland code for more efficiently spare array looping constructs -- that alone would be a win.

But really, my real beef is with the variance in behaviors for the array extras. IMHO the best bet would be for these APIs to grow an opt-in option to skip holes, but that ship probably sailed: an opt-in would be breaking and not statically analyzable; an opt-out would defeat the purpose -- if you're aware of holes you'd almost always want to skip over them, right?

So one reasonable alternative would be to promote holes into a real language construct we can both *visualize *and exploit from userland explicitly, along with fixing as much of the API surface as is practical that creates them implicitly -- starting with holes in array literals.

# Brendan Eich (13 years ago)

On Sep 28, 2011, at 11:21 AM, Dean Landolt wrote:

Hmm, I think I see what you mean, but the hole case is different enough and anyway it has been in the language for 12 years.

True enough, but wouldn't you say it's still commonly misunderstood?

I don't hear enough about hole literal syntax to say that.

Same here, but in comma-first it's not always adjacent:

var middleware = [ context, , csrf , xsite , head , considtional , error ]

You've got to squint a little to see that hole, right?

That is horrible, and a reason to reject comma first. It mixes badly with comma last, and mixing is inevitable -- and I agree, hard to see due to separation onto two or more lines.

So, if we still have holes, is it really worth getting rid of ArrayLiteral support for them? I think not.

But are they of any real use for ArrayLiterals? IMHO a hole in a small array (i.e. an ArrayLiteral) is almost always a mistake,

Or a testcase for the otherwise unwanted feature:

codesearch.google.com/#search/&q=", ," lang:^javascript$&type=cs

Some of those look intentional, and non-testy, though.

But what does it say that the so many are just explicitly testing this edge case? And an entry from wtfjs, right there on the first page :)

I already noted those, but did you look at the ones that looked intentional? We don't get to kick stuff out lightly.

Another wart that springs to mind is the fact that a hole === void 0 but is, in fact, not void 0. I guess technically this is correct -- reifying the index gets you void 0 -- but it's still odd.

This is true with missing properties of any kind.

If there were a way to indexOf for the first hole, for instance, this would at least allow them to be exploited in userland code for more efficiently spare array looping constructs -- that alone would be a win.

Holes are not going away, we agree. Seems to me you're objecting to consequences of holes we can't eliminate without runtime-only compatibility breaks.

But really, my real beef is with the variance in behaviors for the array extras. IMHO the best bet would be for these APIs to grow an opt-in option to skip holes, but that ship probably sailed: an opt-in would be breaking and not statically analyzable; an opt-out would defeat the purpose -- if you're aware of holes you'd almost always want to skip over them, right?

Right, and who wants more knobs on existing APIs.

Probably we should write generic functions in modules, a la itertools2. Let the old stuff on Array.prototype lie still.

So one reasonable alternative would be to promote holes into a real language construct we can both visualize and exploit from userland explicitly, along with fixing as much of the API surface as is practical that creates them implicitly -- starting with holes in array literals.

I agree holes need better handling in future arraylike "extras". Design effort there can start now, using today's JS. I'd welcome it. Perhaps underscore does well already?

# Dean Landolt (13 years ago)

On Wed, Sep 28, 2011 at 2:50 PM, Brendan Eich <brendan at mozilla.com> wrote:

On Sep 28, 2011, at 11:21 AM, Dean Landolt wrote:

Hmm, I think I see what you mean, but the hole case is different enough and

anyway it has been in the language for 12 years.

True enough, but wouldn't you say it's still commonly misunderstood?

I don't hear enough about hole literal syntax to say that.

Touché.

Same here, but in comma-first it's not always adjacent:

var middleware = [ context, , csrf , xsite , head , considtional , error ]

You've got to squint a little to see that hole, right?

That is horrible, and a reason to reject comma first.

Unless this syntax were stricken from the language, of course :)

[snip]

Or a testcase for the otherwise unwanted feature:

codesearch.google.com/#search/&q=", ," lang:^javascript$&type=cscodesearch.google.com/#search/&q=", ," lang:^javascript$&type=cs

Some of those look intentional, and non-testy, though.

But what does it say that the so many are just explicitly testing this edge case? And an entry from wtfjs, right there on the first page :)

I already noted those, but did you look at the ones that looked intentional? We don't get to kick stuff out lightly.

Examples not in a test, comment, or string literal are pretty sparse. Here's the first use I came across:

codesearch.google.com/#sgZapbbRTzk/trunk/sites/ikariam.org/kronos_utils.user.js&q=", ," lang:^javascript$&ct=rc&cd=17&sq=

This could be rewritten to zero-pad the cols and title arrays and use delete explicitly, but yeah, I get that this isn't pretty. A length-setting operation that added the holes to head would be useful. Or even better, a means to slide any array slice around, leaving holes in its wake. But as you say, no one really talks much about holes, so this is all overkill...

Which is why I was suggesting holes be explicit -- perhaps a new type. In order to avoid a runtime compatibility break it would have to be a subtype of void 0. After thinking it through a bit this would be tough to do without introducing yet another type system. So yeah, not worth it for this rare edge case...

Another wart that springs to mind is the fact that a hole === void 0 but is,

in fact, not void 0. I guess technically this is correct -- reifying the index gets you void 0 -- but it's still odd.

This is true with missing properties of any kind.

Sure, but it introspecting objects can't present this problem.

If there were a way to indexOf for the first hole, for instance, this would at least allow them to be exploited in userland code for more efficiently spare array looping constructs -- that alone would be a win.

Holes are not going away, we agree. Seems to me you're objecting to consequences of holes we can't eliminate without runtime-only compatibility breaks.

I was specifically objecting to the ArrayLiteral hole syntax, as well as suggesting the idea of filling these holes with a new type (something akin to the bottom type). With or without the latter the former still smells. Admittedly, without the latter the migration is uglier, but it could stillbe done statically. It seems like a good tradeoff to me -- the only constituencies that really lose are the code golfers, but they've got plenty of clubs in their bags.

One final point: if its worth having holes at all (and IMHO it is) we * definitely *need more API surface to work with them from userland. This means, at the very least, we need a way of finding where holes start that's better than O(N).

[snipped the rest]

# Brendan Eich (13 years ago)

On Sep 28, 2011, at 1:53 PM, Dean Landolt wrote:

Same here, but in comma-first it's not always adjacent:

var middleware = [ context, , csrf , xsite , head , considtional , error ]

You've got to squint a little to see that hole, right?

That is horrible, and a reason to reject comma first.

Unless this syntax were stricken from the language, of course :)

Won't help the downrev browsers in three years, so while it helps in the long run, the comma-first still is to be avoided in the mean while. IMHO.

Which is why I was suggesting holes be explicit -- perhaps a new type

A new type refracts through the entire runtime semantics. Holes are nowhere near a strong enough use-case to motivate yet another undefined-y type (as if null == undefined weren't enough!).

In order to avoid a runtime compatibility break it would have to be a subtype of void 0. After thinking it through a bit this would be tough to do without introducing yet another type system. So yeah, not worth it for this rare edge case...

Whew!

One final point: if its worth having holes at all (and IMHO it is) we definitely need more API surface to work with them from userland. This means, at the very least, we need a way of finding where holes start that's better than O(N).

Agreed -- I want a thousand github flowers to bloom. Do not want TC39 designing APIs and pushing them into standards if we can adopt winning ones from the developer community.

# Mike Shaver (13 years ago)

On Wed, Sep 28, 2011 at 2:50 PM, Brendan Eich <brendan at mozilla.com> wrote:

I agree holes need better handling in future arraylike "extras". Design effort there can start now, using today's JS. I'd welcome it. Perhaps underscore does well already?

IIRC I chose the hole behaviour in the ES5 array extras based on the behaviour of some existing library, though I don't see the rationale documented in any of the bugs I can find.

Mike

# Brendan Eich (13 years ago)

No worries, array extras are a great addition, we just need to keep rolling.

# Mike Shaver (13 years ago)

On Wed, Sep 28, 2011 at 9:11 PM, Brendan Eich <brendan at mozilla.com> wrote:

No worries, array extras are a great addition, we just need to keep rolling.

Oh, no offense taken. I just meant to say that there may be consistency-with-existing-pattern reasons to prefer one hole behaviour over another, is all.

Mike

# Dean Landolt (13 years ago)

On Wed, Sep 28, 2011 at 10:06 PM, Mike Shaver <mike.shaver at gmail.com> wrote:

On Wed, Sep 28, 2011 at 9:11 PM, Brendan Eich <brendan at mozilla.com> wrote:

No worries, array extras are a great addition, we just need to keep rolling.

Oh, no offense taken. I just meant to say that there may be consistency-with-existing-pattern reasons to prefer one hole behaviour over another, is all.

Another reason to prefer the current hole-hopping behavior for array extras is that it's currently the only way to get any efficiency advantage sparse arrays. So regardless of rationale, it's strictly more featureful and almost certainly the intended behavior if, as a developer, you're aware of holes.

But to reiterate the point I made earlier, in order for libraries to take complete ownership of looping constructs we need a better way to detect holes in userland -- something that can be optimized. I was trying to think of a way to overload Array.prototype.indexOf and lastIndexOf but since we don't have a type for holes this isn't really feasible (I'd thought of using NaN as a sigil here as it's otherwise untestable in indexOf, but this would be wrong on so many levels). Regardless of where it goes (on Array, Array.prototype, or in a system module), all we really need is something like a function that takes an index and direction and returns the next hole's start index and length (or end index). I'll put together a proposal if this isn't too controversial.

# Rick Waldron (13 years ago)

On Wed, Sep 28, 2011 at 11:05 PM, Dean Landolt <dean at deanlandolt.com> wrote:

On Wed, Sep 28, 2011 at 10:06 PM, Mike Shaver <mike.shaver at gmail.com>wrote:

On Wed, Sep 28, 2011 at 9:11 PM, Brendan Eich <brendan at mozilla.com> wrote:

No worries, array extras are a great addition, we just need to keep rolling.

Oh, no offense taken. I just meant to say that there may be consistency-with-existing-pattern reasons to prefer one hole behaviour over another, is all.

Another reason to prefer the current hole-hopping behavior for array extras is that it's currently the only way to get any efficiency advantage sparse arrays. So regardless of rationale, it's strictly more featureful and almost certainly the intended behavior if, as a developer, you're aware of holes.

But to reiterate the point I made earlier, in order for libraries to take complete ownership of looping constructs we need a better way to detect holes in userland -- something that can be optimized. I was trying to think of a way to overload Array.prototype.indexOf and lastIndexOf but since we don't have a type for holes this isn't really feasible (I'd thought of using NaN as a sigil here as it's otherwise untestable in indexOf, but this would be wrong on so many levels).

Holes can be detected and skipped by using the "in" operator...

var array = [ 1, , 3, , 5 ];

for ( var i = 0; i < array.length; i++ ) { // Skip accessing in sparse arrays if ( i in array ) { console.log( array[i] ); } }

# Rick Waldron (13 years ago)

On Thu, Sep 29, 2011 at 12:09 AM, Rick Waldron <waldron.rick at gmail.com>wrote:

On Wed, Sep 28, 2011 at 11:05 PM, Dean Landolt <dean at deanlandolt.com>wrote:

On Wed, Sep 28, 2011 at 10:06 PM, Mike Shaver <mike.shaver at gmail.com>wrote:

On Wed, Sep 28, 2011 at 9:11 PM, Brendan Eich <brendan at mozilla.com> wrote:

No worries, array extras are a great addition, we just need to keep rolling.

Oh, no offense taken. I just meant to say that there may be consistency-with-existing-pattern reasons to prefer one hole behaviour over another, is all.

Another reason to prefer the current hole-hopping behavior for array extras is that it's currently the only way to get any efficiency advantage sparse arrays. So regardless of rationale, it's strictly more featureful and almost certainly the intended behavior if, as a developer, you're aware of holes.

But to reiterate the point I made earlier, in order for libraries to take complete ownership of looping constructs we need a better way to detect holes in userland -- something that can be optimized. I was trying to think of a way to overload Array.prototype.indexOf and lastIndexOf but since we don't have a type for holes this isn't really feasible (I'd thought of using NaN as a sigil here as it's otherwise untestable in indexOf, but this would be wrong on so many levels).

Holes can be detected and skipped by using the "in" operator...

var array = [ 1, , 3, , 5 ];

for ( var i = 0; i < array.length; i++ ) { // Skip accessing in sparse arrays if ( i in array ) { console.log( array[i] ); } }

Sorry, that is to say you could do the reverse to detect and access their index positions

# Dean Landolt (12 years ago)

On Thu, Sep 29, 2011 at 12:13 AM, Rick Waldron <waldron.rick at gmail.com>wrote:

On Thu, Sep 29, 2011 at 12:09 AM, Rick Waldron <waldron.rick at gmail.com>wrote:

On Wed, Sep 28, 2011 at 11:05 PM, Dean Landolt <dean at deanlandolt.com>wrote:

On Wed, Sep 28, 2011 at 10:06 PM, Mike Shaver <mike.shaver at gmail.com>wrote:

On Wed, Sep 28, 2011 at 9:11 PM, Brendan Eich <brendan at mozilla.com> wrote:

No worries, array extras are a great addition, we just need to keep rolling.

Oh, no offense taken. I just meant to say that there may be consistency-with-existing-pattern reasons to prefer one hole behaviour over another, is all.

Another reason to prefer the current hole-hopping behavior for array extras is that it's currently the only way to get any efficiency advantage sparse arrays. So regardless of rationale, it's strictly more featureful and almost certainly the intended behavior if, as a developer, you're aware of holes.

But to reiterate the point I made earlier, in order for libraries to take complete ownership of looping constructs we need a better way to detect holes in userland -- something that can be optimized. I was trying to think of a way to overload Array.prototype.indexOf and lastIndexOf but since we don't have a type for holes this isn't really feasible (I'd thought of using NaN as a sigil here as it's otherwise untestable in indexOf, but this would be wrong on so many levels).

Holes can be detected and skipped by using the "in" operator...

var array = [ 1, , 3, , 5 ];

for ( var i = 0; i < array.length; i++ ) { // Skip accessing in sparse arrays if ( i in array ) { console.log( array[i] ); } }

Sorry, that is to say you could do the reverse to detect and access their index positions

I'm aware -- that's why I said we need a better way. This O(N) op is incredibly wasteful on a arrays -- in fact, it completely defeats the purpose. As it stands, the only way to efficiently iterating sparse arrays is with array-extras, and if efficient iteration of sparse arrays is the only reason to have holes in the first place, this is a bit of a fail. The cleanest way I can think of to open the doors to userland optimizations is exposing a method to find hole indexes.

# Allen Wirfs-Brock (12 years ago)

On Sep 29, 2011, at 6:04 AM, Dean Landolt wrote:

On Thu, Sep 29, 2011 at 12:13 AM, Rick Waldron <waldron.rick at gmail.com> wrote:

On Thu, Sep 29, 2011 at 12:09 AM, Rick Waldron <waldron.rick at gmail.com> wrote:

On Wed, Sep 28, 2011 at 11:05 PM, Dean Landolt <dean at deanlandolt.com> wrote:

Holes can be detected and skipped by using the "in" operator...

var array = [ 1, , 3, , 5 ];

for ( var i = 0; i < array.length; i++ ) { // Skip accessing in sparse arrays if ( i in array ) {

Note that 'in' sees inherited properties and that in general when talking about sparseness you need to be explicit about whether or not you want to see "holes" filled by such inherited properties.

In the above algorithm you may really want to say builtinObjProtoHasOwnProperty.call(array,i) instead of in.

  console.log( array[i] );

} }

Sorry, that is to say you could do the reverse to detect and access their index positions

I'm aware -- that's why I said we need a better way. This O(N) op is incredibly wasteful on a arrays -- in fact, it completely defeats the purpose. As it stands, the only way to efficiently iterating sparse arrays is with array-extras, and if efficient iteration of sparse arrays is the only reason to have holes in the first place, this is a bit of a fail. The cleanest way I can think of to open the doors to userland optimizations is exposing a method to find hole indexes.

I agree, implementation can use optimized representations for sparse (and/or non-sparse) arrays. If you are purposefully using sparse arrays then you would really like to leverage the implementations knowledge about sparseness.

For ES next, I would think that some built-in generators that yield exclusively holes or non-holes would be a good way to expose this knowledge. The specification of these generators would use O(n) algorithms but implementations could use internal representation knowledge to make them more efficient.

# Dean Landolt (12 years ago)

On Thu, Sep 29, 2011 at 1:03 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:

On Sep 29, 2011, at 6:04 AM, Dean Landolt wrote:

On Thu, Sep 29, 2011 at 12:13 AM, Rick Waldron <waldron.rick at gmail.com>wrote:

On Thu, Sep 29, 2011 at 12:09 AM, Rick Waldron <waldron.rick at gmail.com>wrote:

On Wed, Sep 28, 2011 at 11:05 PM, Dean Landolt <dean at deanlandolt.com>wrote:

Holes can be detected and skipped by using the "in" operator...

var array = [ 1, , 3, , 5 ];

for ( var i = 0; i < array.length; i++ ) { // Skip accessing in sparse arrays if ( i in array ) {

Note that 'in' sees inherited properties and that in general when talking about sparseness you need to be explicit about whether or not you want to see "holes" filled by such inherited properties.

In the above algorithm you may really want to say builtinObjProtoHasOwnProperty.call(array,i) instead of in.

console.log( array[i] );

} }

Sorry, that is to say you could do the reverse to detect and access their index positions

I'm aware -- that's why I said we need a better way. This O(N) op is incredibly wasteful on a arrays -- in fact, it completely defeats the purpose. As it stands, the only way to efficiently iterating sparse arrays is with array-extras, and if efficient iteration of sparse arrays is the only reason to have holes in the first place, this is a bit of a fail. The cleanest way I can think of to open the doors to userland optimizations is exposing a method to find hole indexes.

I agree, implementation can use optimized representations for sparse (and/or non-sparse) arrays. If you are purposefully using sparse arrays then you would really like to leverage the implementations knowledge about sparseness.

For ES next, I would think that some built-in generators that yield exclusively holes or non-holes would be a good way to expose this knowledge. The specification of these generators would use O(n) algorithms but implementations could use internal representation knowledge to make them more efficient.

I'd considered this too, but it doesn't play very nicely with Brendan's notion of a thousand github modules blooming. You may need more control over iteration, like controlling where to start and stop iteration.

There's an actual use case around binary data -- for instance using holes could come in handy in node's Buffer API. IIRC there was a time they didn't clear buffers on instantiation, a security hazard. It can be expensive to fill a buffer with arbitrary ints -- holes would likely be a better model. Being able to borrow ideas and API surface from the sparse array model could be incredibly valuable for people working with things like binary data and databases.

This is the reason I'm still pushing on the issue -- there are a whole range of use cases hiding in sparse arrays, a lot more than head-to-tail iteration. Exposing an API to query for holes would formalize and complete a long-standing almost-feature of the language.

Oh, and all that said, holes in ArrayLiterals should still die a painful death :)