151

我不明白Lua这部分决定背后的理由。为什么索引从 1 开始?我已经读过(和其他许多人一样)这篇很棒的论文。在我看来,这是一种学习和编程非常愉快的语言的一个奇怪角落。不要误会我的意思,Lua 很棒,但必须在某个地方做出解释。我发现的大部分内容(在网上)只是说索引从 1 开始。句号。

阅读它的设计师对这个主题的看法会很有趣。

请注意,我是 Lua 的“非常”初学者,我希望我不会遗漏一些关于表格的明显内容。

4

9 回答 9

179

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

虽然一开始我也觉得它们很奇怪,但我已经学会了喜欢从 0 开始的数组。但是我对 Lua 的基于 1 的数组感到满意,尤其是通过使用 Lua 的通用for循环和ipairs运算符——我通常可以避免担心数组是如何被索引的。

于 2010-05-07T02:42:34.650 回答
52

Programming in 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 的索引肯定会成为更大的障碍。最终,作者想要一些对他们有用的东西;我承认我不知道他们最初的目标是什么,但从那以后它可能已经改变了。

于 2010-05-07T02:15:32.820 回答
17

我的理解是,之所以这样,只是因为作者认为这是一种很好的方式,而在他们将语言发布给公众之后,这个决定就变得相当僵化了。(我怀疑如果他们今天改变它,将会付出惨痛的代价!)除此之外,我从未见过任何特别的理由。

于 2010-05-07T01:58:33.807 回答
10

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

于 2012-08-06T09:05:47.277 回答
2

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

事实上,这里很酷的是内部 lua 库会将一些传递的 0 视为 1。使用 ipairs 时要小心。
所以:("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
于 2017-12-22T11:38:51.590 回答
2

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

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

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

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

和 Lua。这是使用 C 的表索引的 lua 5.3.5 代码:

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的索引,他们选择了易于理解的纯粹更新程序,放弃了便利性和有效性。

于 2021-02-03T10:59:11.367 回答
0

真正的原因是该语言是葡萄牙法律中定义的实现,而主要的发展中心在巴西,他们的偏好是避免使用零或空或无作为索引或下标。但是,在某些版本中,该语言确实允许在表创建函数中使用 1 以外的起始索引。

于 2010-11-24T14:18:15.837 回答
-1

在您的示例中,table[0]始终return nil(null)除非您自己为其分配值,例如table[0] = 'some value'然后table[0]将 return'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]))
于 2016-11-07T09:12:30.333 回答
-13

对每个人来说都是有意义的,如果

table = {}

table是空的。那么,当

table == {something}

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

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

我的英语不会变得更好,这是我最好的语法。如果您不喜欢它,您可以不继续阅读它,但是为试图帮助的人提供 -rep 会使人们根本不想提供帮助,尤其是对于语法之类的东西。我是一个数字和变量,而不是语法的人。对不起。

于 2011-12-06T09:12:30.607 回答