Question

ANSWER : only use table.* functions on sequences (arrays/list) (tables with only consecutive integer keys starting at 1). Their behavior is undefined on non array-like table: they may or may not work as you could expect.


In Lua 5.1 table.insert( t, index, value ) is supposed to move up values if index already exist in the table, right ?

But it doesn't always do that :

local t = {}
table.insert( t, 4, 5 )
table.insert( t, 5, 6 )
table.insert( t, 4, 4 ) -- this erase the value 5 at key 4
-- t[4] = 4, t[5] = 6, t[6] = nil

local t = {}
table.insert( t, 1 )
table.insert( t, 2 )
table.insert( t, 3 )

table.insert( t, 6, 7 )
table.insert( t, 6, 6 ) -- this erase the value 7 at key 6
-- t[6] = 6, t[7] = nil

But :

local t = {}
table.insert( t, 1 ) -- these two lines were added
table.insert( t, 2 ) 
table.insert( t, 4, 5 )
table.insert( t, 5, 6 )
table.insert( t, 4, 4 ) -- now it moves the values up
-- t[4] = 4, t[5] = 5, t[6] = 5

local t = {}
table.insert( t, 1 )
table.insert( t, 2 )
table.insert( t, 3 )
table.insert( t, 4 ) -- this line was added
table.insert( t, 6, 7 )
table.insert( t, 6, 6 ) -- now it moves the values up
-- t[6] = 6, t[7] = 7

This works like that in LuaForWindows command line as well an application that runs lua scripts (CraftStudio), both using Lua 5.1.

It seems that it happens when

  • (number of entries) < index (for the first example)
  • (number of entries) < index-1 (for the second example)

So, is this an expected behavior, a bug of Lua 5.1 ? Is there another formula to predict if this will happens or not ?

Thanks a lot

Was it helpful?

Solution

A table is a list only if its indices are consecutive: t[1], t[2], t[3], ... t[i], ... t[N] are non-nil for all i from 1 to N. Your code is using a table as an associative array (map in C++, dictionary in Python), so the table operations won't work (actually, they might work sometimes, since it is undefined behavior). From the Lua 5.1 ref manual:

Most functions in the table library assume that the table represents an array or a list.

Unfortunately the ref manual does not explicitly define "array or list", but browsing the ref man where it discusses arrays indicates that two simple rules are sufficient to be a "regular" or "ordinary" array: no nil values for t[i] for i=1 to N.

You may be better off creating a table with t[i]=0 for i=1 to N where N is larger than anything you expect in that function call (for instance, the largest value in some other table). Once you've completed your insertions, you can set all remaining t[i] which = 0 to nil, but only do that if you are not going to need the table ops.

The other thing you could do is that if you find that an item should be inserted before i, check if t[i-1] is nil; if it is, set it to 0 or -1 or some value that represents "dummy". Repeat this check for i-2 etc.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top