How is it in practice?
How is it in practice?
For loops are more natural when indexing from one; for loops in most languages specify inclusive ranges, but indexed containers typically advertise their, rather than their maximum index. You don't notice this much in C and derived languages because the for loop in those languages is more flexible (and more open to abuse).
More concretely, this is a very common idiom in Delphi when dealing with 0-based containers:
for i := 0 to list.Count - 1 do
The '- 1' on the end is ugly. What's needed is a way of expressing a half-closed interval, but that's not common in programming languages (despite it being a great aid to correctly expressing many algorithms concisely).Let's say you want to insert into the middle of an array, at x, with count elements (and presumed free space at the end). You need to move all the elements from x to the end up one. Let's suppose you have a move(array, fromIndex, toIndex, count) function that can do that. In 0-based languages:
move(array, x, x + 1, count - x)
But you need to adjust it for 1-based languages: move(array, x, x + 1, count - x + 1)
However, you can mitigate it by changing how the move() function takes its parameters: move(array, startIndex, endIndex, newIndex)
move(array, x, count, x + 1)
If everyone is consistent, and APIs are designed with 1-based indexing in mind, most of the issues go away. It's when there are mixed styles that things get painful.A slightly lesser known construction in Ruby, the ... Range operator does this.
It won't be fixed, because it would break existing programs in too subtle ways. Lua compatiility is sometimes broken, but only if it breaks into easy-to-find-and-fix ways.
Using a single dimensional array as a 2 dimensional array relies on zero indexing.
index = y * width + x
array[index]
Using modulo to covert an index back to 2 dimensions relies on 0 indexing x = index % width
y = index / width
Skipping a prefix in a string. prefix = "ABC"
string = "ABCdef"
unprefixed = string[prefix.length:]
I'm sure there are tons of others. Yes, you can add 1 or subtract 1 in the right places. That's the annoying part of it though.For example, to get a prefix of length 'n', you need characters 0 through n-1 with zero-based indexing and 1 through n with one-based indexing. (That Python hides the -1 when using a [0:n] range is a convenience; the subtraction still happens internally.)
Similarly, to get the last element of a one-based array with a[length(a)] and the last element of a zero-based array with a[length(a)-1].
What it comes down to is that sometimes you have to write +1 or -1 for zero-based indexing where you can avoid it for one-based indexing and vice versa. What is not the case is that it only universally happens for one of those schemes.
More elaborate and rigorous: http://www.cs.utexas.edu/~EWD/transcriptions/EWD08xx/EWD831....
Whether it's a very mildly annoying annoyance or it's the most annoying thing in the world seems to depend entirely on your personality.
arr[0] = n
and write your own for loops, e.g. for i=0,10 do print arr[i] end
The only catch being that the length operator (#arr) will be off by one. for i, x in ipairs(mylist) do
so the 0 vs 1 based indexing is made irrelevant. There are some times where mess up but overall most Lua users don't think its much of an issue. (Personally, I find the lack of a ternary conditional operator much more annoying)http://lua.2524044.n2.nabble.com/petition-to-keep-ipairs-ali...
Edit: both are from 2010. This never became final perhaps?