admin管理员组

文章数量:1318183

I started learning Lua recently, as far as I can tell, when I don't specify the index, the function table.insert tries to put the value in the first nil in the table.

Why then is it that in table t the 10 ends up at index 4, in table y the 10 ends up at index 2, and in table x it ends up at index 5?

local t = {1, nil, 2}
table.insert(t,10)
for i = 1, 6 do
    print(string.format("t[%d] = %s", i, t[i]))
end

print()

local y = {1, nil, 2}
y[5]= 3
table.insert(y, 10)
for i = 1, 6 do
    print(string.format("y[%d] = %s", i, y[i]))
end

print()

local x = {1, nil, 2}
table.insert(x,2,20)
x[6]= 3
table.insert(x,10)
for i = 1, 6 do
    print(string.format("x[%d] = %s", i, x[i]))
end


Terminal result:
t[1] = 1
t[2] = nil
t[3] = 2
t[4] = 10
t[5] = nil
t[6] = nil

y[1] = 1
y[2] = 10
y[3] = 2
y[4] = nil
y[5] = 3
y[6] = nil

x[1] = 1
x[2] = 20
x[3] = nil
x[4] = 2
x[5] = 10
x[6] = 3

I started learning Lua recently, as far as I can tell, when I don't specify the index, the function table.insert tries to put the value in the first nil in the table.

Why then is it that in table t the 10 ends up at index 4, in table y the 10 ends up at index 2, and in table x it ends up at index 5?

local t = {1, nil, 2}
table.insert(t,10)
for i = 1, 6 do
    print(string.format("t[%d] = %s", i, t[i]))
end

print()

local y = {1, nil, 2}
y[5]= 3
table.insert(y, 10)
for i = 1, 6 do
    print(string.format("y[%d] = %s", i, y[i]))
end

print()

local x = {1, nil, 2}
table.insert(x,2,20)
x[6]= 3
table.insert(x,10)
for i = 1, 6 do
    print(string.format("x[%d] = %s", i, x[i]))
end


Terminal result:
t[1] = 1
t[2] = nil
t[3] = 2
t[4] = 10
t[5] = nil
t[6] = nil

y[1] = 1
y[2] = 10
y[3] = 2
y[4] = nil
y[5] = 3
y[6] = nil

x[1] = 1
x[2] = 20
x[3] = nil
x[4] = 2
x[5] = 10
x[6] = 3
Share Improve this question edited Jan 30 at 0:11 Oka 26.4k6 gold badges48 silver badges56 bronze badges asked Jan 29 at 23:40 RafaelRafael 311 silver badge2 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 3

From table.insert, we can see that table.insert(t, 42) behaves as

t[#t + 1] = 42

From 3.4.7 – The Length Operator:

The length operator applied on a table returns a border in that table. A border in a table t is any non-negative integer that satisfies the following condition:

(border == 0 or t[border] ~= nil) and
(t[border + 1] == nil or border == math.maxinteger)

[ ... ]
A table with exactly one border is called a sequence.
[ ... ]
When t is a sequence, #t returns its only border, which corresponds to the intuitive notion of the length of the sequence. When t is not a sequence, #t can return any of its borders. (The exact one depends on details of the internal representation of the table, which in turn can depend on how the table was populated and the memory addresses of its non-numeric keys.)

In other words, calling table.insert on tables with multiple borders, without specifying a position, will insert the value at an index determined by the internal representation of the table.

Avoid this if portability is a concern. For example, on my system, the results of your program differ between the reference implementation of Lua and LuaJIT.

$ lua -v
Lua 5.4.6  Copyright (C) 1994-2023 Lua., PUC-Rio
$ luajit -v
LuaJIT 2.1.1734355927 -- Copyright (C) 2005-2023 Mike Pall. https://luajit./
$ diff <(lua example.lua) <(luajit example.lua)
2c2
< t[2] = nil
---
> t[2] = 10
4c4
< t[4] = 10
---
> t[4] = nil
17,19c17,19
< x[3] = nil
< x[4] = 2
< x[5] = 10
---
> x[3] = 2
> x[4] = 10
> x[5] = nil

本文标签: luatableinsert not replacing the first nil position in the tableStack Overflow