ndarray icon indicating copy to clipboard operation
ndarray copied to clipboard

Reconsider negative indexing?

Open droundy opened this issue 7 years ago • 6 comments

I've not yet used ndarray, but looking at its description, it sounds like it follows Python's approach of using negative indices to could back from the end of an array? I would strongly suggest reconsidering that. It is the feature of numpy that in my experience most commonly results in hard to find bugs for now users.

droundy avatar Mar 30 '18 14:03 droundy

The current status is:

  • Negative indices are supported in the various .slice*() methods.
  • Negative indices are not supported anywhere else, although I've been planning to change that.

My thoughts on this are:

  • It is important to make indexing from the end of the axis a convenient operation, because it is quite common.

  • Rust has a significant advantage over Python in this case: Rust has unsigned integer primitives as part of the core language. If you use usize to index an array, you don't have to worry about negative indices, because usize can't be negative.

  • Allowing negative indices is a nice way to handle indexing from the end of an axis, but it's not the only convenient way to do so. For example, we could support something like .slice(s![3..5, ..END-7]) or .slice(s![3..5, ..back(7)]).

  • I don't have a strong preference for negative indices over something a little more verbose, but negative indices are simpler to implement, and Rust's usize type seems sufficient to avoid bugs related to negative indices.

@droundy Do you agree that usize makes this not much of a concern?

@bluss and others: What are your thoughts on this?

Edit: I realized that while we could have .slice(s![3..5, 1..END-7]) or .slice(s![3..5, 1..back(7)]), the implementation would be pretty hacky and would prevent us from catching some other types of bugs. A cleaner implementation would require .slice(s![3;5, 1;END-7]) or .slice(s![3..5, front(1)..back(7)]), neither of which I like very much.

jturner314 avatar Mar 30 '18 18:03 jturner314

I agree that allowing usize would greatly reduce the danger of allowing negative indices.

Personally, I'd still prefer a solution for counting backwards that is more like normal rust.

droundy avatar Mar 30 '18 18:03 droundy

Just to clarify, you can currently use usize everywhere; that's already implemented.

jturner314 avatar Mar 30 '18 18:03 jturner314

My lousy 2 cents, one month later:

  • The biggest footgun of indexing with actual negative indices is the fact that -0 is still 0. (rather than referring to the point just past the end)
  • Negative strides with non-negative indices do not have this danger.

ExpHP avatar Apr 28 '18 20:04 ExpHP

Hi, I just want to say that I really like END-7. I'm using Python a lot, and I have had some bugs with negative indexes which weren't meant to be negative. I understand that requiring usize should prevent that, but I don't really like the requirement to use usize. In a program I wrote I had to write "as usize" many times, and it wasn't pleasant. OTOH, END-7 is very explicit in what it means, and also easy to type.

noamraph avatar Nov 12 '19 10:11 noamraph

@jturner314 https://matterjs-republican.github.io/alistair31/

Emlyn-typhoid avatar Oct 07 '25 20:10 Emlyn-typhoid