问题 我可以强迫Lua的表索引从零开始吗?


我读过Lua,它几乎是完美的语言,但是存在严重的错误。它是基于单一的索引。我还读到它有一个在索引0处设置值的功能,但它没有计算表长度,字符串操作仍然是基于一个。所以这个功能毫无意义。

我不想煽动基于一个或基于零。我只想问是否有强制使用从零开始的索引的功能。


3972
2017-08-07 13:20


起源

我可以问为什么这是一个问题?好的,所以你更喜欢0索引,但为什么你不能使用1索引? - gnud
我也有这个问题:)无论什么有意义,我几乎每次都在lua中弄错了。我已经习惯了使用其他基于零的语言,因为我的lua代码因为这一件事而充满了错误! - jcoder
我不认为有一些标志会将lua从1切换到0,因此除了修改需要使用非标准lua(我在这里dub lua0)的lua之外我不知道怎么做 - Dan D.
@gnud这显然是个问题,因为它是C的脚本,而不是XPath的脚本。当然我可以使用1索引,但这对我来说效率太低,因为我很愚蠢,因为我觉得一次使用双索引系统很难。 (我必须使用C作为主机系统)并且必须翻译脚本和主机之间的任何索引数据交换。我可以肯定这会导致更多我觉得难以处理的错误。 - Eonil
@Judge我认为这是一个不同的问题,因为我问了一种改变语言默认行为的方法,问题是要求语言设计的理性原因。 - Eonil


答案:


我认为Lua已经拥有了你需要让它基于0的功能。不幸的是,我所指的功能是Lua的开源许可证。

我无法找到Lua的补丁或分支,它改变了该语言的基于1的性质。

不幸的是,要求Lua将其更改为0也会破坏向后兼容性。所有当前附加模块的丢失可能是为了易于使用而付出的代价。


2
2017-08-07 18:34



似乎没有简单的方法来覆盖这种行为。 - Eonil


我知道这个问题已经有1年了,但我认为未来的搜索者会对这个事实感兴趣,CFF Explorer包含一个脚本语言(带补丁的Lua),它有0索引表补丁:

http://www.ntcore.com/files/cffscriptv2.htm

此外,在上面的文档中,作者声称他必须禁用大多数标准库函数,因为它们与0索引数组不兼容,所以请重申你对这个问题的思考过程:)


3
2017-09-15 18:13





使用0索引数组实际上非常简单:

local array={
[0]="zero",
    "one",
    "two"
}

for i=0,#array do
    print(array[i])
end

您可以使用 #array 不减去1,因为长度运算符实际上返回最高索引(技术上,第一个零之前的键),而不是实际的“长度”(无论如何在Lua中都没有意义)。

对于字符串运算符,您可能只需要创建重复的函数(尽管可能有更好的方法)

ipairs() 也只支持1索引,所以你必须定义自己的函数或只使用常规 for 代替。


3
2018-06-20 19:23





即使有一个 #define TABLE_START_INDEX 1 在Lua的消息来源(我不相信它)你会通过改变它来拍摄你自己的腿。这是因为大多数库使用基于1的索引。因此,执行类似以下操作的任何代码都会破坏。

对于i = 1,#t do ...结束

您当然可以使用迭代器甚至创建辅助函数来避免这种情况。

function get_first(t)return t [1] end

可能虽然您尝试解决的实际问题比从0更改为基于1的索引更难。


1
2017-08-07 14:13



不。这不是一个真正的问题。真正的问题是基本语言应该是基于0的索引语言的C语言。必须正确转换脚本和主机之间的索引数据交换。我必须立即处理双索引系统。 - Eonil


Eonil对ponzao答案的评论: 真正的问题是基本语言应该是基于0的索引语言的C语言。必须正确转换脚本和主机之间的索引数据交换。

如果要将C数据结构公开给Lua,请使用 userdata 打包他们。您可以根据自己的喜好使用metatable来使索引行为。这样,您就可以确保正确的翻译。


1
2017-11-22 11:55





肮脏的方法有一些缺点:

function zeroIndexed(tbl)
    local mt = {}
    mt.data = tbl
    mt.__index = function(t, k)
        return mt.data[(type(k) == "number" and k + 1 or k)]
    end
    mt.__newindex = function(t, k, v)
        mt.data[(type(k) == "number" and k + 1 or k)] = v
    end
    mt.__len = function()
        return #mt.data
    end
    return setmetatable({}, mt)
end
t = zeroIndexed({5, 6, 7})
print(t[0], t[1], t[2])
t[0] = 4
print(t[0], #t)
t[#t] = 8
print(t[#t - 1], #t)

Lua 5.2输出:

5       6       7
4       3
8       4

在Lua 5.1 #t 回报 0 因为 __len metamethod 表和字符串不受尊重。

但请记住 table.insert 和其他表格方法不再适用于此,因为插入现在通过 t[#t] = x

我不建议使用它。


1
2018-02-06 14:38



你为什么不推荐?对于表插入问题? - Daniel Sperry
这个有一个问题:ipairs和pair迭代器仍将返回基于1的数组的索引。 - val


您可以通过使用知道不同索引库的迭代器来修复此lua-flaw:

function iarray(a)
  local n = 0
  local s = #a
  if a[0] ~= nil then
    n = -1
  end
  return function()
    n = n + 1
    if n <= s then return n,a[n] end
  end
end

但是,您仍然需要手动添加第0个元素:

用法示例:

myArray = {1,2,3,4,5}
myArray[0] = 0
for _,e in iarray(myArray) do
  -- do something with element e
end

0
2017-11-05 15:12