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

时间:2010-05-07 01:52:59

标签: arrays lua lua-table

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

阅读其设计师对该主题的看法将非常有趣。

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

12 个答案:

答案 0 :(得分:125)

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

虽然我在开始时发现它们很奇怪,但我学会了喜欢基于0的数组。但是我可以通过Lua的基于1的数组获得,尤其是 使用Lua的通用for循环和ipairs运算符 - 我通常可以避免担心数组的索引方式。

答案 1 :(得分:40)

Lua中的编程首次讨论表格时,他们提到:

  

由于您可以使用任何值索引表,因此您可以使用任何数字来启动数组的索引。但是,在Lua中习惯于使用1启动数组(而不是在C中启动数组),并且有几个设施坚持这个约定。

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

无论如何,使用基于1的索引有一些几个便利。即,#(长度)运算符:t[#t]访问表的最后一个(数字)索引,t[#t+1]访问1 过去最后一个索引。对于尚未接触过基于0的索引的人,#t+1可以更直观地移动到列表的末尾。还有Lua的for i = 1,#t构造,我认为它与前一点相同,“1到长度”比将“0到长度减去1”更为明智。

但是,如果你不能打破基于0的索引的思维模式,那么Lua基于1的索引肯定会成为一个障碍。最终,作者想要一些适用于他们的东西;而且我承认我不知道他们的原始目标是什么,但从那时起它可能已经改变了。

答案 2 :(得分:22)

有一个非常重要的理由不计算1中的数组: 如果数组从零开始,您可以以自然的方式将它们用作代数环。例如。我们有一周的日子(day={'mo', 'tu', 'we'...),我们希望通过它们循环。那么写下心灵的意义要小得多:

nextday = day[(i+1)%7]  as it is in almost every other language

比:

nextday = day[i%7+1] as it is in lua

起初似乎并不那么糟糕,但试着以另一种方式循环一周。

或者更一般地说:如果索引集缺少零,它缺少添加的中性元素。无论何时在索引计算中需要,都必须转移指数。

我是一名数学家,但我已经接受了这样一个事实,即在编程时,从零开始计算只是更好的选择..

答案 3 :(得分:14)

我的理解是,就是这样,因为作者认为这是一种很好的方式,并且在他们将语言推向公众之后,决定大大加重了。 (我怀疑如果他们今天改变它将会付出代价!)除此之外,我从未见过特别的理由。

答案 4 :(得分:5)

也许是一个不太重要的观点,但我还没有提到过:在字符串中的第一个和最后一个字符分别为1和-1而不是0和-1这一事实有更好的对称性。

答案 5 :(得分:1)

table [0]将总是返回nil(null),除非你自己为它赋值[0] ='某些值'然后表[0]将返回一些值'你指定的。

这是一个例子:

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

答案 6 :(得分:1)

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

事实上,这里很酷的东西是内部lua库会把Some传递给0作为1。使用ipairs时要小心谨慎 所以:(“abc”):sub(0,1)==“a”和(“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

答案 7 :(得分:0)

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

答案 8 :(得分:-1)

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

答案 9 :(得分:-1)

我最常用的表之一是 arg 表,起始索引是...

# /usr/local/bin/lua -i -e "for k,v in pairs(arg) do print(k..'='..v) end"
Lua 5.4.3  Copyright (C) 1994-2021 Lua.org, PUC-Rio
1=-i
2=-e
3=for k,v in pairs(arg) do print(k..'='..v) end
0=/usr/local/bin/lua

...零。
但是根据我如何调用 Lua(例如作为 shellscript 函数),它也可以是负数。
那么,这个shellscript函数...

lua () 
{ 
    ( /usr/local/bin/lua "${@}" -- .luarc )
}

...调用:lua -i
让我们看起来像这样...

0=.luarc
-3=/usr/local/bin/lua
-2=-i
-1=--

这是什么规则?
我决定让我每次检查 arg 中的序列。

答案 10 :(得分:-2)

它是在Sol之后制作的,Sol是一种由人们和没有任何编程经验的人制作的编程语言

示例

让我们假设您要将长度为3个字节的记录写入位置i的数组

在基于0的语言上,这是找到开始写入记录的字节偏移量的公式:

var ptr = 3 * i

第一个元素(i = 0)给出偏移量0。 第二个元素(i = 1)给出偏移量3。 等等...

在基于1的语言中,首先尝试相同的方法:

var ptr = 3 * i

第一个位置(i = 1)给出3作为偏移但你应该得到1.所以你减去2以得到1.

var ptr = 3 * i - 2

到目前为止一切顺利。现在,您尝试使用i=2公式。你得到4并且它是正确的。

通用公式为:

var ptr = L * (i-1) + 1

另一个例子

连接两个字符串时计算下一个偏移量也会导致复杂的公式:

以0为基础,你可以找到这样的偏移量:

var ptr = Len(string1) + Len(string2)

以1为基础的公式

var ptr = Len(string1) + Len(string2) + 1

我将矩阵乘法作为练习: - )

基本上使用基于1的表示法,您最终会在整个地方写入+1和-1,以便调整值。代码只是尖叫你使用基于0的索引方法

从数学的角度来看,在基于0或基于1的计算机上,索引基本上是从起点的偏移,不是 p>

答案 11 :(得分:-11)

每个人都有意义,如果是

table = {}

目前,table为空。所以,什么时候

table == {something}

如果您知道我的意思,那么该表包含的内容就是table中的索引1。

我的意思是它的表[0]存在,它的表= {},它是空的,现在程序员不会调用空表,它设置它们,然后填充它,它将是无用的每次要调用它时都会找到一个空表,因此只需创建一个空表就更简单了。

我的英语不会好起来,这是我最好的语法。 如果你不喜欢它,你可以自由地继续阅读它,但是给那些试图帮助的人提供-rep会让人们根本不想帮助,尤其是像语法这样的东西。 我是一个有数字和变量的人,而不是语法。遗憾。