从一开始计数

lua-users home
wiki

与当今最流行的语言相反,Lua 数组索引表示数组中的序数位置,而不是数组头的偏移量。(不幸的是,这种方案被称为“从一开始计数”,导致许多人将其辩护为自然计数方式。实际上,争论在于使用偏移量还是序数来指示序列中的元素。)

Lua 核心代码中只有一处是这种情况:解析构造函数,例如 {10,20,30} 。从 1 开始的约定仅由库强制执行,库不是语言的一部分。--lhf

Lua 5.1 之后不再是这种情况,因为 # 运算符也依赖于基索引为 1。


你误解了长度运算符。引用 Nick Gammon 在下面几段中的说法

来自 Lua 手册

表 t 的长度定义为任何整数索引 n,使得 t[n] 不为 nil 且 t[n+1] 为 nil;

该定义(来自 Lua 5.1 手册)意味着表 { [-3] = 0 } 的长度为 -3,而完全为空的表 {} 根本没有长度(而不是长度为 0)。这比从零开始计数更不直观。出于某种原因,PUC-Lua 5.1 不遵守此定义:#{ [-3] == 0 } == 0。(Lua 5.2 手册将定义更改为显式从 1 开始计数的定义。对于空表来说,这仍然是相当不明确的,除非你知道范围 {1..n} 对于小于 1 的 n 应该是什么——定义它而不陷入类似的陷阱是相当棘手的。)--f.

哦,让我们结束这个话题:定义一个代理表到真实表,并覆盖索引元方法,以便在 i 为正数时访问真实表中的 i-1。决定何时将负索引直接映射到真实表,或者是否进一步处理它们。决定对真实表中的索引 0 你将做什么。

完成之后,在你需要从零开始计数时使用代理表。在你需要库函数时使用真实表。为了便于记忆,将你的表命名为 'tablename1',将代理命名为 'tablename0'。问题解决。


如果你是一个被称为“脚本编写者”或“非程序员”的人,这里呼吁你对未来的语言采取立场。让大家知道你完全有能力理解偏移的概念,就像任何程序员一样。Lua 列表的基索引为 1,因为人们认为这对于非程序员来说是最友好的,因为它使索引与序数元素位置相对应。然而,这种可疑的让步给程序员带来了很多麻烦,进而降低了他们为你提供工作工具的效率。一个原因是 Lua 与 C 紧密耦合,C 对数组使用基索引 0——索引表示数组头部偏移量。这意味着在 Lua 和 C 两侧工作的程序员必须不断地在代码和思维中切换引用,这很烦人且容易出错。此外,事实证明,使用偏移量与一种特定范围指定方式相辅相成,其中末尾不包括在内(称为半开范围),而使用序数位置则没有。半开范围允许更自然地处理零长度范围,从而导致更简洁和一致的程序。

作为一个 C++ 和 Lua 程序员,我完全不同意这种抱怨。从 1 开始计数是“自然”的计数方式。在数学中,每个人都从 1 开始计数。从 0 开始计数只对 C 的约定有利,即数组和指针是等价的,并且 a[i] 与 *(a+i) 相同。此外,我认为,程序员很容易适应非 C 式的计数方式。然而,这使得 Lua 对“休闲程序员”来说更加直观。--PeterPrade

同意,这确实是一篇抱怨 :-)。但是,你的论点没有解决半开范围如何允许更简洁的编码问题,而这正是我主要观点。在处理范围 Lua 时,程序往往会充斥着 +1,因为 Lua 不使用半开范围,而在 C++ 中(尤其是在使用 STL 时,它在整个过程中都使用这种范围样式),这种情况不会发生。此外,我同意从一开始就计数对人类来说是自然的(我从未说过相反的话),但是用 [n, n-1] 表示零长度范围非常笨拙。用地板上的一个起点,然后是一个落后一步的目的地来告诉某人“向前迈出零步”是不自然的。相反,人类可以很容易地理解“向前迈出零步”,方法是在地板上指示一个起点,以及一个相同的终点——对应于半开范围 [n, n)。--JohnBelmonte

集合论者、逻辑学家和组合学家从零开始计数。Z/nZ(模 n 整数)环的元素通常命名为 {0, 1, ..., n-1},因此代数学家也从零开始计数。所有这些学科都与 CS 和编程密切相关。在分析中,人们通常从 1 开始计数,但这并不重要——自然数集通常在那里用于其拓扑结构,或者仅仅作为具有明确定义的“向后移动”和“向前移动”操作的方便索引集(即使这样,如果包含零,定义会更优雅),使得起点选择相当随意(它也可能是 42)。选择 1 通常是出于习惯,为了避免破坏“向后兼容性”(即与使用基于一的编号的材料的相互理解),或者为了避免在分母/指数/任何东西中考虑零。--f

半开区间有时可以使代码更简洁,有时则不然。我见过(也犯过)很多关于半开区间和闭合区间的边界错误。例如,C 数组中最后一个元素的索引比数组长度小 1,这会导致代码中出现各种 -1;当然,有一些方法可以消除这些错误,但我不会说我的 Lua 代码中 +1 的数量比我的 C 代码中 -1 的数量更多。然而,关于半开区间,有一个严重的问题:你需要能够表示不在区间内的量。因此,例如,长度为 256 的字符串的索引类型至少需要是 short,即使每个有效索引都是一个字节。类似地,指向向量末端的半开区间描述符包含一个地址,该地址不包含在向量的存储中,并且很可能是一个指向不同对象的有效指针;这会使保守垃圾回收变得复杂,例如。(至少有一个保守垃圾回收器故意过度分配以弥补这个问题。)我并没有偏袒哪一方:两者都是有效的,都有优点,也有缺点。--RiciLake

你的论点站不住脚,RiciLake。你有一个包含 256 个字节的数组,你使用“闭合”表示法,其中 (n, m) 表示 [n, n+1, n+2 ... m-1, m],来表示该数组中的区间。如上所述,零长度区间的表示为 (n, n-1);例如,[4, 3]。那么从零开始的零长度区间的表示是什么?(0, 256) 有其他含义。因此,你关于数组索引需要多少位的论点对于半开区间和闭合区间的表示来说都是一样的。对于像 Lua 这样的语言来说,它也是无关紧要的,因为你无法选择使用多少位。--KragenJavierSitaker?

就像从一开始计数一样,我认为闭合区间比半开区间更直观,至少当你没有谈论零长度区间的特殊情况时。当我提到“直观”时,我的意思是对于那些至少几年没有编程的人来说,它更自然。--PeterPrade

我没有统计过,但我认为大量的编程语言都是从零开始计数的……而且由于我学习的第一门语言是 C,从一开始计数对我来说很混乱——事实上,我写了很多从零开始的数组的糟糕的 Lua 代码——AdrianPerez

虽然从零开始计数有其优点,但我发现从一开始计数更自然,即使在编程时也是如此。对我来说,在 Lua 和 C 之间切换没有问题,因为过去我在 Visual Basic 和 C 之间切换了很多次——匿名

第一个是第 1 个,而不是第 0 个 --Kazimir Majorinc

“我正在评估 Lua 作为我应用程序中的嵌入式脚本语言,到目前为止,我看到的一切都非常积极,直到我意识到 Lua 从索引 1 开始计数。糟糕。糟糕。太糟糕了。糟糕到足以让我考虑把整个东西都扔掉。至于理由,即使不应该有任何必要:),长度为 N 的数组的索引是模 N 整数环的自然映射,它有很多不错的特性。例如,当你想循环访问你的数组时,你只需执行 index = (index+1) %N。用从 1 开始的索引做同样的事情很痛苦。此外,它使得将 C 例程绑定到 Lua 非常痛苦。”

index = index % N + 1 --Milano Carvalho

没错,突然之间我们有了 bug 和额外的工作,而这些工作本来是不需要的。此外,程序员现在必须记住“索引是位置,违反了模运算的前提条件,还是它实际上是模运算?”最后,它的逆是什么?是“modindex = index - 1 % N”还是“modindex = index % N - 1”?这是一个陷阱问题:它是“modindex = (index - 1) % N”。 --Andrew Lentvorski

同意。Lua C 库接口到 C 使用了对 C 来说不自然的约定。例如,当将 Lua 表解析为 C 数组时,你必须记住使用 iterator+1 来访问表索引。--DanHollis?


从 0 开始计数对我个人来说不是什么大问题;从 1 开始计数只是 Lua 数据类型缺乏的问题的症状,绝不是问题的全部。我的问题是数据类型缺乏,包括那些数组,无论以 1 为基还是以 0 为基。表可能有一个紧密打包的“数组”部分,但我并不热衷于我的 33 个单词数组占用 64 个单词的空间(必须是 2 的幂)。不要让我开始谈论我甚至不能有一个字节数组,而只能有巨大的双精度浮点数(或双精度数,或者 Lua 编译时选择的唯一(1)数值数据类型)。是的,我知道 Lua 使得将它粘合到 C 中的真实数组变得很容易。但它就不是真正的 Lua 了,它是一种二等公民的“userdata”类型,我不能真正把它当作一个真正的列表来对待。

Lua 5.1 提供了 lua_createtable() API 调用,它允许你指定表的数组大小(精确地)。你也可以指定哈希大小,但那部分总是限制为 2 的幂。如果你创建了一个具有指定数组大小的表,只要你不强制表扩展,它的数组部分就会精确地是那个大小,所以如果你事先知道表的大小,它就会正常工作。绑定小原子对象的数组,比如 int,在 5.1 中也变得稍微容易一些,因为有可能覆盖 # 运算符,但是为了让 userdata 真正像一个 Lua 表一样工作,你需要修改 ipairs 的默认定义,以及可能 unpack 的默认定义。我已经在 Wiki 上的 GeneralizedPairsAndIpairs 上放了一些关于前者的代码,以防有人需要。--RiciLake

这是一个很好的观点,我也一直为此苦恼。将大型 C 结构体与 Lua 交互,尤其是大型结构体的 C 数组,并不轻松。Lua 没有提供直接的映射方式。--DanHollis?


Lua 源代码中有一个常量 lua_Number,默认设置为 double。类似地,定义一个常量 lua_FirstIndex(例如)并将其默认设置为 1,用于表示第一个索引,可能很有趣。Lua 中所有与数组第一个索引相关的部分(例如,ipairforeachi 等)都应该使用此常量。如果用户希望将此常量更改为 0 并重新编译,他们可以在自己的风险下使用从 0 开始的 Lua 表,这可能会导致兼容性问题。相同的常量应该可以在 Lua 中访问,以允许脚本可移植或独立于索引数组的第一个值。--Salvador Espana


计算机科学中是否应该从零或一计数是一个经典问题。我发现 Edsger Dijkstra 的文章“为什么编号应该从零开始”(http://www.cs.utexas.edu/users/EWD/ewd08xx/EWD831.PDF) 中的论点非常有说服力,我成为了一个强烈的从零开始计数的倡导者。太可惜了,Lua 建议从 1 开始。这将使表/数组构造变得笨拙: {[0]=10, 20, 30} ,并且表库函数的价值也会降低。--Ulrich Hoffmann <[email protected]>

是的,这是一篇很棒的文章。我特别喜欢第一句话:“为了表示自然数 2、3、...、12 的子序列 [...]。”现在,将这句话与计算机语言应该主要向读者传达其意图,而只是偶然地向计算机传达其意图的指标结合起来,我们就会发现,即使对于 Dijkstra 来说,最自然的符号也是包含式的...得出你自己的结论。


从一开始计数更“直观”,但从零开始计数在算法上要好得多。这是一种用于编写由计算机执行的算法的编程语言,而不是人类之间日常对话的语言。程序员很聪明,他们能弄明白。不要把他们当孩子对待。:) --DanHollis?


我赞成使用半开区间而不是闭区间,因此从 0 开始计数而不是从 1 开始计数。不仅零长度区间自然地表示为 [n,n),而且相邻区间也很好地加起来 -- [a,b)+[b,c)=[a,c) -- 不会在两端过度加倍。得到的区间长度为 (b-a)+(c-b)=c-a,并且任何或两个分量都可以是零长度。此外,可以考虑 `负区间' [m,n),其中 m>n,并且区间的加法仍然有效,现在甚至可以从非零区间获得零长度区间。

现在,考虑数字 abx。`xab 之间' 的正确表达式,在 min(a,b)<=x<max(a,b)(半开区间)的意义上是 (a<=x)=(x<b)。如果是闭区间(...<=x<=...),我们就不会有这么好的表达式。-- Boyko Bantchev


我个人对从 1 开始计数没有问题。一方面,字符串中第一个字符是 1,最后一个字符是 -1 的习惯用法是一个好主意。如果第一个字符是 0,这将行不通。

作为一种脚本语言,它的首要任务是易于脚本编写者使用。一个包含 5 个元素的数组,最后一个元素是数字 5,肯定比它在元素 4 处结束更容易向非专业脚本编写者解释?

我在我的系统中将许多客户端函数与接口连接起来,以将其工作原理暴露给 Lua。在许多情况下,基于零或一的问题甚至不适用。例如,许多使用字符串键(在这种情况下问题就消失了),或者它们不使用任何类型的数组。

如果你希望 Lua 成为一种通用的脚本语言,我当然不建议使用编译时选项,这样发布的一半 Lua 脚本基于零,一半基于 1。这样做会打开通往噩梦的大门。我甚至无法想象如果你想与 LuaSocketLuaCom 等东西进行接口连接,这将如何工作。这些将假设当前约定,即数组从 1 开始,并且许多都附带了 Windows 的预编译二进制文件。如果你在基于零的系统上运行,这些要么根本无法工作,要么每个包的作者都必须在他们的代码中添加测试,以确定基数是什么,这肯定会失去改变它的任何优势。-- NickGammon


还有一点,在内部,Lua 在许多地方使用 1 作为第一个,-1 作为最后一个的约定。例如

double num = luaL_checknumber (L, 1); /* get first item on stack */

因此,将 Lua 与 C 连接的程序员非常熟悉该约定 - 你必须熟悉。同样,如果你将数组设为基于零,你会改变它吗?在这种情况下,你如何从堆栈中获取最后一个元素(当前为 -1)?

上面的一些帖子并没有真正提到它们是否指的是字符串。例如,字符串中的第一个项目

c = string.sub ("ABC", 1) --> "A"

你会把那个也设为零吗?如果是这样,你怎么得到最后一个项目?-- NickGammon

使用 -1 作为最后一个元素的别名与半开范围(即从零开始计数)完全一致。参见 Python。事实上,它比闭合范围更一致。假设列表是循环的,你可以从开头移动到结尾,然后以“短路”方式返回。位置 0(列表的开头)左侧的一个是 -1(列表的结尾)。换句话说,你可以从你的位置减去 1 来向左移动,这是很自然的。如果你从 1 开始列表,它会在开头和结尾之间产生两个位置的奇怪间隙。要向左移动,你需要从你的位置减去 1,除非你在位置 1,在这种情况下,你需要减去 2。

那么你是否也建议 greatest_index + 1 循环到第一个元素?如果不是,在从最后一个元素(用正索引指定)到第一个元素时,仍然会有这些“奇怪”的跳跃,所以这个论点没有任何意义。

不,如果你想让索引循环,使用 i 模 n。这个方程的简单性是索引偏移的吸引人的地方之一。

是的,这是真的。但是,鉴于“事情已经做完了”,我建议需要“从零开始计数”方法的应用程序(出于数学或其他原因),只需定义自己的 foreachi 函数来解决当前的行为。毕竟,没有什么能阻止你将元素放到当前表格的第 0 位。

如果你想让表格构造函数从 0 开始,请这样做

t = { [0] = "a", "b", "c" }  -- a is in position 0, b is in 1 and so on

-- NickGammon

不幸的是,#t 评估为 2。很多问题都源于数字与序数的混淆。当索引是偏移量时,0 是数组中第一个项目的偏移量。如果我们在口语中使用数字时更谨慎地保留类型信息,那么在这方面就会有更少的争议。在数学中,将非负整数 n 实现为从 0 到 n-1(包括)的数字集,比将其识别为从 1 到 n 的数字集提供了更简洁的公式。-- GavinWraith

虽然在数学中,矩阵和向量通常是 1 索引的[1][2][3]。类似地,在 LuaMatrix 中,第一个元素被引用为 mtx[1][1]。序列可能会有更多变化[4]。关于数学软件,Mathcad 默认情况下是 0 索引(虽然可以更改),而 Matlab、Maple 和 Mathematica 是 1 索引。--DavidManura


但是,#t(或 table.getn)没有定义为返回表中元素的数量。例如

t = { foo = 1, bar = 2 } ; print (table.getn (t))  --> 0

来自 Lua 手册

表 t 的长度定义为任何整数索引 n,使得 t[n] 不为 nil 且 t[n+1] 为 nil;

我的例子与定义一致。#t 返回最后一个项目的索引。

-- NickGammon

不是的。t[0] 是 nil。根据该定义,该表根本没有定义的长度。见上文。--f


Visual Basic 和尤其是 JavaScript? 是两种类似于 Lua 的语言。对于从这些语言迁移过来的非技术用户来说,有一个低进入门槛会很好。在 JavaScript? 中,数组从 0 开始索引。在 Visual Basic 中,数组默认情况下从 0 开始索引。(更改默认值强烈不建议,也不受现代实现(如 VB.Net)的支持。)


我正在查看 Perl 是从 0 还是 1 开始索引(似乎是零),并且在我的 Perl 手册中找到了这个宝石

数组下标 n,其中 n 是任何非负整数,始终引用数组元素 n+1。

很明显,我们不会在这里达成一致,但是你不觉得这有点令人困惑吗?“下标 n ... 指的是元素 n+1?”。至少在 Lua 中,下标 n 指的是元素 n。

-- NickGammon

只有当你的基数为 0 并且你将索引视为位置时,它才会令人困惑。如果你的基数为 0,那么索引最好被认为是从列表开头的偏移量,而不是位置。这与加文刚刚提出的观点相同。一般来说,偏移量在编程中比位置更有用。


“自然数集”在美国是指大于或等于零的整数集,而在苏联是指大于零的整数集。这就像缩进一样。

恕我直言,从 1 开始计数很棒。第一个元素是 1,最后一个元素是 -1。无需记住“这不是数学,这不是自然的事情,习惯它”,就像你在处理 Python 中的索引时一样。

-- muntyan

而 Lua 允许你在整数中存储 0 - 那么它会得到哪个元素呢?


Lua 的主要优势在于它是可嵌入性最强的脚本语言之一 - 它实际上并不是最适合一般编程任务的顶级脚本语言(Python 和 Perl 更好)。作为嵌入式脚本语言,它将被嵌入到编译语言中。几乎所有这些语言都使用基于 0 的索引,因此大多数新用户都会有这种参考框架。VB 曾经有过这场争论(以及选择动态选项),据我所知,人们投票支持基于 0 的索引。所以让我们就这样做,结束它吧。-- GRB

完全正确 - JeanClaudeWippler


请不要以第一人称写作,而不署名。

所以所有这些数论都付诸东流了吗?天哪,你出生后就一岁了,克拉克先生关于 2001 年的说法是错误的。-0 的模数有多有用。抱歉,但我认为整个想法需要重新思考、修改和纠正。不,从一开始就不是像一个人写的那样自然,而是因为零是直观假设的;因此;无需说明。但好老的计算机并不假设。只是我的想法 ---trav
在 BASIC 中,你可以从你想要的任何数字开始,比如
 DIM arrayname(5 to 18)
在 Forth 中,你也可以从你想要的任何数字开始,比如
 HERE 14 ALLOT 5 - CONSTANT arrayname

非程序员实际上已经从 0 开始计数,而没有意识到。在计数时,猜猜人们用什么作为十位、百位、千位等的第一个数字?提示:它不是 1。所以用 1 作为第一个单位非常不一致。这种不一致性是为什么以 19 开头的年份是 20 世纪:我们只是缺少 0 世纪。这种不一致性也是为什么很多人认为 21 世纪始于 2000 年。通过假设这一点,他们只是更方便地从...零开始计数。另一个例子:一天/下午的第一小时用哪个数字?提示:同样,它不是 1。从一开始计数时的另一个不一致:我们使用十个数字,现在请说出最后一个数字?参见 Stefan Ram 的文章“数字从零开始”,了解更多非技术性、非数学性的例子。

从一开始计数似乎是来自一元制的一个非常古老的遗留问题。我们在发明零的时候应该摆脱它,但不幸的是我们没有。


从 1 开始计数是我不使用 Lua 的首要原因。除此之外,它是一门非常棒的语言,但使用半开区间编程要容易得多。当人们告诉我“从一开始计数更自然”时,我不同意。这只是一个来自过去的旧遗留问题。如果你真的仔细想想,从 0 开始计数更有意义。

--Zifre


Zifre,你不是应该说,“从 1 开始计数是我不使用 Lua 的 *零* 个原因”吗?毕竟,你声称从零开始计数对你来说更有意义。

我们来打个赌。我们去公园,找一些随机的人。我们会给他们看三块石头排成一排,然后让他们大声数石头。如果有人说,“零,一,二”,那么你赢。如果每个人都说,“一,二,三”,那么我赢。我想我会一直赢这个赌注。没有人从零开始计数,因为这没有意义。当数组的第一个元素用 0 访问时,该数字代表的是偏移量,而不是索引。问题不是关于计数,而是关于数组应该使用偏移量还是索引。

当然,使用偏移量而不是索引确实有一些优势。但很难反驳这一点:如果数组使用索引,那么“第 n 个”元素可以用数字“n”访问。你想要第四个元素吗?那么使用 4。想要第十个?那么使用 10。这很有意义,并且有它自己的一套不错的属性。不幸的是,许多程序员在这个问题上思想封闭,并且以某种方式说服自己相信荒谬的陈述,例如,“从 0 开始计数更有意义。”(然后,在他们自己的帖子中,说明他们实际上是从一开始计数的,就像地球上的其他人一样。)

我们来打第二个赌。在让大家数石头之后,我们会说,“请指向石头一”。如果有人指向中间的石头,那么你赢了。否则,我赢了。同样,我不明白我怎么会输掉这个赌注。-- 匿名

Zifre 与匿名在这一页的讨论中没有添加任何内容。你读过第一段吗?问题不是关于从一或零开始计数,而是关于如何在一个序列中指示一个元素。使用偏移量会导致更少的边缘情况,从而使代码和 API 更简单。这与公园里的人如何计数无关。--JohnBelmonte

考虑到 Lua 目前的主要用途之一是业余脚本编写,例如在允许你成为一名不熟练的程序员但仍然可以享受定制的礼物的地方,公园里的人如何计数是相当相关的。并不是说所有东西都应该为了万能的消费者而变得简单,尤其是程序员用来进行业务的工具,但由于偏移量与基数的争论在很大程度上是一个概念问题,与你如何内化代码应该意味着什么有关,为什么指责 Lua 迎合公园里的人,在那里石头数组中的第一块石头是石头 1?对于那些不熟悉偏移量的人来说,偏移量是一个进入的门槛。

好吧,让一台计算机来数这 3 块石头。你会得到类似这样的结果:00、01、10。你在这里错过了大局:你不是在编程人,而是在编程计算机。了解计算机的内部结构通常会有所帮助。你永远无法让一台计算机完全理解你(或者也许你可以,但如果是这样的话,你应该获得诺贝尔奖)。但是,你可以完全理解一台计算机 :) -- shiretu


我在这方面开始一个新页面,试图总结这个问题的几个方面:[IndexIntervalFormatIssue]。[DeniSpir]
那个页面上有一个巨大的误解,DeniSpir。在“程序员太多”部分,半开区间被描述为[n,n],而它们应该是[n,n)。

此外,这个说法:[a,b]+[b,c] 应该是这个:[a,b]+[b+1,c] 完全是错误的,因为最初的命题需要半开区间,在这种情况下,它看起来像这样:[a,b)+[b,c)

因此,投诉完全是错误的,因为[a,b)+[b,c) 不会包含两次 b。我将纠正那部分并删除关于 [a,b]+[b+1,c] 的抱怨,因为它是毫无意义的。--Tim


JohnBelmonte,使用偏移量不会导致更简单的代码 API。同意,边缘情况更少,但不要试图说服人们喜欢或不喜欢特定的编程模式。这里重要的是 Lua 应该支持多样性。我自己在设计基于 1 的代码时遇到了困难,并且比你所谓的“边缘情况”更容易出错。换句话说,我本能地知道如何使用我在其他 10001 种编程语言中开发的技能来避免边缘情况,而不是采用你“安全”的开发“更简单代码”的方法。真的,这只是一个品味问题。你不能把人归类为“你很蠢,因为你用这种方式编码,你很聪明,因为你用那种方式编码”。尽管我讨厌 Lua 的这一点,但我仍然非常喜欢它,因为它还有很多其他积极的方面。但我确实错过了一点……能够在编译时指定索引基数……--shiretu
这是错误的。原因如下:Edsger Dijkstra 关于从 0 开始数组索引的说明(pdf,1982)[5]。-- 匿名


我尝试在 Lua 5.3.4 源代码分发版中打补丁,包括所有官方库:lua-base-0。开源[6]。如果您有兴趣,请去检查(并将它移植到最新的 lua,为它编写一些测试用例)我是否遗漏了什么。

一些例外

string.gmatch 中, "%0" 用于整个匹配,而 "%1%2"... 用于第一个、第二个捕获。保持不变。

args 表的订阅定义保持不变,但请注意,长度运算符现在将返回一个大 1 的数字。

math.random 是一个不确定的点。目前的状态最适合实用性:当提供 1 个参数时,它返回 [0, n),当提供 2 个参数时,它返回 [a, b]。

数值循环是另一种。当前状态是:对于for i=0,3为{0,1,2},对于for i=3,0,-1为{3,2,1}。

我正在考虑将后者也改为{2,1,0},因为它只是作为反向迭代。但这在定义上看起来很丑,也可能出现一些浮点数问题。(但我真的想知道,谁在生产环境中使用过它?) 你怎么看?

表.remove的边界情况,其中i==#t+1i==#t 基于0)被删除。我不理解它。它现在会引发错误。

其余部分应该很简单,包括一些负索引被支持为反转的情况,在这种情况下,它将主要像python一样工作。

我反对基于1的表的另一个理由是:它在与JSON(一种广泛使用的交换格式)进行转换时会导致问题和混淆。

--farter

另请参阅


最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2018年3月19日凌晨2:54 GMT (差异)