News for hackers. Stuff that matters.
Re:Moving from Ruby to Rust by bsder on Thursday February 14, 2019 @06:42PM (#19167173)
There is no more correct. There is simply more to purpose.

0-based indexing won in programming because it is simply more to purpose in programming. We rarely operate on ranges, but we operate on offsets all the time.

And 0-based wasn't solely "C won so 0 won". We had 1-based languages for a LONG time, and, if they were sufficiently superior, they should have displaced C. They did not.

In addition, in proper programming languages you don't count--you iterate, fold, accumulate, etc.--and avoid the index altogether because it is error-prone.

1-based indexing causes all kinds of havoc in circular ranges. In particular when you try to access things in a circular manner (very common in programming--uncommon in mathematics), it causes grief.

// 1 based

new_index = index % N + 1

new_index = (index - 1) % N // Careful: the parentheses are REQUIRED

new_index = (new_index == 0 ? N : new_index)

// 0 based

new_index = (index + 1) % N

new_index = (index - 1) % N

Range discussion from Dijkstra in 1982: https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/E...

Re:Moving from Ruby to Rust by xiphias2 on Thursday February 14, 2019 @06:52PM (#19167234)
Actually what's funny here is that (index - 1) % N doesn't work in C, as it can be negative. You have to use (index+N-1) % N.

I still prefer 0 based indexing (for example for calculating the size of an array), but the worst thing is inconsistency between languages. 0 won, that's it.

Re:Moving from Ruby to Rust by bsder on Thursday February 14, 2019 @07:16PM (#19167383)
Oh, that's hilarious. I tested this in Python where it worked fine and forgot that C has a "broken" modulo operator:

Python:

  >>> -1 % 20
  19
C:

  printf("%d\n", (-1 % 20));
  -1
Even worse, it still fails even on unsigned:

  printf("%d\n", ((unsigned int)0 - (unsigned int)1) % 20);
  15
So you still need to add N:

  printf("%d\n", ((unsigned int)0 - (unsigned int)1 + 20) % 20);
  19
Thanks for the reminder of humility.

(Side Note: For those reading this, the C operator isn't "broken", per se. There are three properties that modulo can adhere to but two of the three are mutually exclusive.)

Re:Moving from Ruby to Rust by m-ou-se on Friday February 15, 2019 @02:19AM (#19169094)
C does not have a modulo operator. It has a remainder operator, which works perfectly fine. Calling C's `%` a 'broken modulo operator' is like calling `+` a 'broken minus operator'. Quite a few languages have separate operators, keywords, or functions for 'modulo' and 'remainder'.
Re:Moving from Ruby to Rust by int_19h on Thursday February 14, 2019 @08:10PM (#19167692)
> We rarely operate on ranges, but we operate on offsets all the time.

I would disagree with that assertion. Maybe it was true historically, but just look at how often ranges are used today - the fact that many languages have an abstraction for them in the core library is a testament to that.

I would also argue that having ranges (and underlying iterators) as opaque abstractions is preferable to conflating them with indices. Then you can have your cake and eat it too - the elements are counted naturally, but if you have an iterator to the first element, you can deal with 0-based offsets just as naturally.

Re:Moving from Ruby to Rust by Certhas on Thursday February 14, 2019 @07:02PM (#19167298)
Could also be that C is superior in other ways, there isn't really a big difference between 0 and 1 based indexing, and thus 0 based won on the back of Cs other strengths.

The Dijkstra discussion is only aesthetic preference, nothing more.

Edit:

In Julia the examples would also idiomatically be written in terms of the provided mod1 function:

    new_index = mod1(old_index + 1, N)
    new_index = mod1(old_index - 1, N)
Re:Moving from Ruby to Rust by bsder on Thursday February 14, 2019 @07:35PM (#19167518)
> Could also be that C is superior in other ways, there isn't really a big difference between 0 and 1 based indexing, and thus 0 based won on the back of Cs other strengths.

Possibly, but then 1-based indexing certainly isn't enough of a positive to overcome the other stuff. And that's evidence, too.

> The Dijkstra discussion is only aesthetic preference, nothing more.

Dijkstra's comment says that people using the other 3 conventions were committing more errors--that's data.

> In Julia the examples would also idiomatically be written in terms of the provided mod1 function:

Agreed. The proper way is to encapsulate that behind a function so you don't have to think about it.

However, if you have to unpack that and repack it all the time (for example, Lua calling C), then you can't just encapsulate and forget about it.