Hacker News new | ask | show | jobs
by ufo 1992 days ago
I think I might disagree with #3. I find that having arr[-1] point towards the last element of the array can hide accidental off-by-one errors. It's also a bit weird how the arrays are zero-based if you access them normaly but one-based if you access them backwards. IMO it's more consistent to make the negative indexes behave the same way as an out of bounds access like arr[arr.length + 1]
2 comments

If your mental model is that an array is zero-indexed but circular, I think arr[-1] still is consistent with that model. If you don’t think of arrays as circular, then sure, it doesn’t make sense.

I’m still in agreement that negative indices make it more confusing than just calculating based off the length, but I get why they exist.

The mental model doesn’t really jive with circularity since arr[arr.length] is not the same as arr[0] in any language that I know of. With a circle, you would expect that arr[0], arr[length], and arr[2*length] are all identical.
You can also think of negative indexes as a shorthand for length-N. arr[-1] is the same as arr[len(arr)-1].
Certainly negative indexes being out-of-bounds would be the most consistent behaviour, but that requires giving up the index-from-end functionality (or, at least giving up up with the defualt array access syntax).

If you are going to have negative indexing, there isn't really a better alternative than 1 based indexes; since you can't exactly do arr[-0]

You can actually do it (I'm not saying it's a good idea), there's a way to differentiate between -0 and 0:

    > Object.is(0, -0)
    false
I was going to make a comment about this not working for integer types; but then I remembered that JavaScript doesn't have integers, so I guess it technically works.
FWIW, I fully support the notation `arr[-0]` as a solution to this problem.
Even better: just make all arrays one-based instead of zero-based ;)
So then what should this code produce?

    i = -0
    return arr[i]
So then what should this code produce?

    i = -0
    return arr[i]
That code would (assuming an integer value; the question is interesting without reference to the implementation of JavaScript) return arr[0], the first element. Don't think of arr[-1] as indexing the array with a negative number that might have been a positive number. Think of array access from the front, arr[ ], and array access from the back, arr[- ], as separate operations with separate syntax, each of which can accept only nonnegative numbers. arr[i] is of the first type, so you get the first element counted from the front.
Actually, I think that might work in Javascript! All the numbers are IEE754 floating point numbers and there are separate values for positive and negative zero.
iirc using numeric literal values there's a coercion step—a console example:

  let arr = new Array(10);
  // 1e1 => 10
  arr[1e1] = 1;
  console.log(`arr[10]  === 1 => ${arr[10]  === 1}`)
  console.log(`arr[1e1] === 1 => ${arr[1e1] === 1}`)

So -0 becomes 0:

  arr[0] = 2;
  console.log(`arr[0]   === 2 => ${arr[0]  === 2}`);
  console.log(`arr[-0]  === 2 => ${arr[-0] === 2}`);
  arr[-0] = 3;
  console.log(`arr[0]   === 3 => ${arr[0]  === 3}`);
  console.log(`arr[-0]  === 3 => ${arr[-0] === 3}`);