Why do Lua arrays(tables) start at 1 instead of 0?
I don't understand the rationale behind the decision of this part of Lua. Why does indexing start at 1? I have read (as many others did) this great paper. It seems to me 开发者_如何转开发a strange corner of a language that is very pleasant to learn and program. Don't get me wrong, Lua is just great but there has to be an explanation somewhere. Most of what I found (on the web) is just saying the index starts at 1. Full stop.
It would be very interesting to read what its designers said about the subject.
Note that I am "very" beginner in Lua, I hope I am not missing something obvious about tables.
Lua is descended from Sol, a language designed for petroleum engineers with no formal training in computer programming. People not trained in computing think it is damned weird to start counting at zero. By adopting 1-based array and string indexing, the Lua designers avoided confounding the expectations of their first clients and sponsors.
Although I too found them weird at the beginning, I have learned to love 0-based arrays. But I get by OK with Lua's 1-based arrays, especially by
using Lua's generic for
loop and the ipairs
operator—I can usually avoid worrying about just how arrays are indexed.
In Programming in Lua's first discussion of tables, they mention:
Since you can index a table with any value, you can start the indices of an array with any number that pleases you. However, it is customary in Lua to start arrays with 1 (and not with 0, as in C) and several facilities stick to this convention.
Later on, in the chapter on data structures, they say almost the same thing again: that Lua's built-in facilities assume 1-based indexing.
Anyway, there are a couple conveniences to using 1-based indexing. Namely, the #
(length) operator: t[#t]
access the last (numeric) index of the table, and t[#t+1]
accesses 1 past the last index. To someone who hasn't already been exposed to 0-based indexing, #t+1
would be more intuitive to move past the end of a list. There's also Lua's for i = 1,#t
construct, which I believe falls under the same category as the previous point that "1 to the length" can be more sensible than indexing "0 to the length minus 1".
But, if you can't break the mindset of 0-based indexing, then Lua's 1-based indexing can certainly be more of a hindrance. Ultimately, the authors wanted something that worked for them; and I'll admit I don't know what their original goal was, but it's probably changed since then.
My understanding is that it's that way just because the authors thought it would be a good way to do it, and after they rolled the language out to the public that decision calcified considerably. (I suspect there would be hell to pay were they to change it today!) I've never seen a particular justification beyond that.
Perhaps a less significant point, but one I haven't heard mentioned yet: there is better symmetry in the fact that the first and last characters in a string are at 1 and -1 respectively, instead of 0 and -1.
Lua libraries prefer to use indices which start at 1. However, you can use any index you want. You can use 0, you can use 1, you can use -5. It is even in their manual, which can be found at (https://www.lua.org/pil/11.1.html).
In fact, something cool here is internal lua libraries will treat SOME passed 0's as 1's. Just be cautious when using ipairs.
So that: ("abc"):sub(0,1) == "a" and ("abc"):sub(1,1) == "a"
will be true.
You can start an array at index 0, 1, or any other value:
-- creates an array with indices from -5 to 5
a = {}
for i=-5, 5 do
a[i] = 0
end
The specific definitions of array index in C and Lua, are different.
In C array, it means: item address offset of the array address.
In Lua array, it means: the n-th item in array.
Why most languages use 0-based index? Because the compiler code with offset definition
is more convenient and effective. They mostly handle addresses.
And the Lua. This is the code of lua 5.3.5 for table index with C:
const TValue *luaH_getint (Table *t, lua_Integer key) {
if (l_castS2U(key) - 1 < t->sizearray)
return &t->array[key - 1];
else {
Node *n = hashint(t, key);
for (;;) {
if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key)
return gval(n);
else {
int nx = gnext(n);
if (nx == 0) break;
n += nx;
}
}
return luaO_nilobject;
}
}
We should focus on the code &t->array[key - 1]
, it have a subtraction operation. It is not effective compared with 0-based index.
But, the 1-based index is more neared with human being languages. We focus more on n-th item in English, Chinese, Japanese and also.
So, I guess the Lua designers choose 1-based index, they choose easy understanding for pure newer of program, give up the convenience and effectiveness.
In your example, table[0]
will always return nil(null)
, unless you assign value to it yourself, like table[0] = 'some value'
and then table[0]
will return 'some value'
, which you assigned.
Here's an example:
tbl = {"some"}
print("tbl[0]=" .. tostring(tbl[0]))
print("tbl[1]=" .. tostring(tbl[1]))
nothing = {}
print("nothing[0]=" .. tostring(nothing[0]))
print("nothing[1]=" .. tostring(nothing[1]))
nothing[0] = "hey"
print("(after assign)\nnothing[0]=" .. tostring(nothing[0]))
The real reason is that the language is an implementation of the definition in a law of Portugal and the major development centre was in Brazil and their preference is to avoid the use of zero or empty or nothing as an index or subscript. However the language does permit the use of a start index other than 1 in a table creating function in some versions.
It makes sense to everyone, that if
table = {}
table
is empty. So, when
table == {something}
The table contains something so what it contains is index 1 in table
, if you know what I mean.
What I meant is that table[0]
exists, and its table = {}
, which is empty, now a programmer won't call a empty table, it sets them, and then fills it, it will be useless to find an empty table every time you want to call it, so it's simpler to just create an empty table.
精彩评论