为什么 Lua 数组(表)从1开始而不是0?

我不明白 Lua 的这一部分决定背后的理由。为什么索引从1开始?我读过(和其他人一样) 这篇伟大的论文。对我来说,这似乎是一种非常好学和编程的语言的一个奇怪的角落。不要误会我的意思,Lua 是很好,但是总会有一个解释的。我(在网上)找到的大部分内容只是说索引从1开始。句号。

如果能读到它的设计者是怎么说这个主题的,那将是非常有趣的。

注意,我是 Lua 的“非常”初学者,我希望我没有遗漏关于表的一些显而易见的东西。

77189 次浏览

我的理解是,这样做只是因为作者认为这将是一个很好的方式来做到这一点,并在他们推出的语言向公众后,决定钙化相当大。(我怀疑,如果他们今天改变它,将付出惨痛的代价!)我从没见过比这更合理的解释了。

Lua 编程关于表格的第一次讨论中,他们提到:

由于可以使用任何值对表进行索引,因此可以使用任何令您满意的数字来开始数组的索引。然而,在 Lua 中通常使用1(而不是 C 中的0)来启动数组,有几个工具遵循这个约定。

稍后,在关于数据结构的章节中,他们又说了几乎相同的事情: Lua 的内置工具假设基于1的索引。

无论如何,使用基于1的索引有一个 一对方便。也就是说,#(长度)操作符: t[#t]访问表的最后一个(数值)索引,而 t[#t+1]访问1 过去的最后一个索引。对于那些还没有接触过基于0的索引的人来说,#t+1会更直观地跳过列表的末尾。还有 Lua 的 for i = 1,#t结构,我认为它与前面的观点属于同一类别,即“1的长度”可能比索引“0的长度减去1”更合理。

但是,如果您不能打破基于0的索引思维,那么 Lua 的基于1的索引肯定会成为更大的障碍。最终,作者想要的东西,工作的 他们; 我承认,我不知道他们的 原创的目标是什么,但它可能已经改变了。

Lua 是 Sol 的后裔,Sol 是一种为石油工程师设计的语言,他们没有接受过正规的计算机编程培训。没有接受过计算机培训的人认为从零开始计数是非常奇怪的。通过采用基于1的数组和字符串索引,Lua 设计人员避免了混淆第一批客户和赞助商的期望。

虽然一开始我也觉得它们很奇怪,但我已经学会了喜欢基于0的数组。但是我对 Lua 的基于1的数组还可以,特别是通过 通过使用 Lua 的通用 for循环和 ipairs操作符,我通常可以避免担心数组是如何被索引的。

真正的原因是,语言是葡萄牙法律中定义的执行,主要的发展中心在巴西,他们倾向于避免使用零或空或无作为索引或下标。但是,该语言允许在某些版本的创建函数的表中使用除1之外的开始索引。

大家都能理解

table = {}

table是空的,所以

table == {something}

该表包含一些内容,所以它包含的内容是 table中的索引1,如果你知道我的意思的话。

我的意思是,table[0]是存在的,它的 table = {}是空的,现在程序员不会调用一个空表,它设置它们,然后填充它,每次你想要调用它的时候,找到一个空表是没有用的,所以创建一个空表更简单。

也许有一点没有那么重要,但是我还没有听说过: 字符串中的第一个字符和最后一个字符分别是1和 -1,而不是0和 -1,这是一个更好的对称性。

在你的例子中,table[0]总是强大返回 nil(null)除非你自己给它赋值,就像 table[0] = 'some value',然后 table[0]将返回 'some value',你给它赋值。

这里有一个例子:

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]))

Lua 库更喜欢使用从1开始的索引。但是,您可以使用任何您想要的索引。可以使用0,可以使用1,可以使用 -5。它甚至在他们的手册中,可以在(https://www.lua.org/pil/11.1.html)找到。

事实上,一些很酷的东西在这里是内部 lua 库将对待一些传递0的作为1的。使用 iears 时要小心。
因此: ("abc"):sub(0,1) == "a" and ("abc"):sub(1,1) == "a"将为真。

 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

C 和 Lua 中数组索引的具体定义是不同的。

在 C 数组中,它的意思是: 数组地址的项地址偏移量

在 Lua 数组中,它的意思是: 数组中的第 n 项

为什么大多数语言使用从0开始的索引?因为使用 offset definition的编译器代码更方便、更有效。他们主要处理地址。

还有 Lua,这是 Lua 5.3.5的代码,用于带 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;
}
}

我们应该把重点放在代码 &t->array[key - 1]上,它有一个减法运算,与0为基础的索引相比是不有效的。

但是,基于1的索引更接近于人类语言。我们更注重英语、汉语、日语和其他语言的第 N 项。

因此,我猜测 Lua 设计者选择了基于1的索引,他们选择了易于理解的纯新的程序,放弃了方便和有效性。