very interesting indeed !
the following inconsistency is reproducible with 1 in any position. just add more nils.
t={nil,1} print(#t, table.maxn(t)) --=\> 2,2 t={nil,1,nil} print(#t, table.maxn(t)) --=\> 0,2 t={nil,1,nil,nil} print(#t, table.maxn(t)) --=\> 2,2 t={nil,1,nil,nil,nil} print(#t, table.maxn(t)) --=\> 2,2 t={nil,1,nil,nil,nil,nil} print(#t, table.maxn(t)) --=\> 0,2 t={nil,1,nil,nil,nil,nil,nil} print(#t, table.maxn(t)) --=\> 0,2 t={nil,1,nil,nil,nil,nil,nil,nil} print(#t, table.maxn(t)) --=\> 2,2
here’s what i can surmise from some research:
tables in Lua, at their heart, are really associative arrays, an object (class). indicies for stored values can be numbers, strings, etc, but NOT ‘nil’.
tables used as arrays are not “pure” arrays as we think of in languages like C. they are a construct made from an associative array, thus it’s possible to run into issues when wanting to store a ‘nil’ as a valid value.
http://www.lua.org/pil/2.5.html
however, from some strict definitions of the ‘#’ operator, it seems like it should still work, or at least be consistent based on our small examples above:
“The length operator # only applies from 1 to the last non-nil element.”
http://www.luafaq.org/gotchas.html#T6.1
but from official docs, it seems like that behavior isn’t guaranteed:
“the length of a table t **is only defined** if the table is a sequence, … Note that a table like
{10, 20, nil, 40}
is not a sequence, because it has the key 4 but does not have the key 3.”
http://www.lua.org/manual/5.2/manual.html#3.4.6
many pages suggest avoid using these “sparse arrays” to bypass the issue:
“Try not to put nil in arrays. It will work if you know what you’re doing, but the length operator # will be confused and standard table functions like table.sort() will complain bitterly. Sparse arrays have their uses, if you remember not to depend on #”
http://www.luafaq.org/gotchas.html#T6.4
“If you have a table like {‘a’, ‘b’, nil, ‘d’, ‘e’} then that is *not* considered to be treating a Lua table as an array, and therefore, anything you try to do on that table as if it *was an array (for example: getting its length with #, … are not guaranteed to work”
http://lua-for-ags.wikispaces.com/IntroducingLuaDataDefinition
some better news is that there was a long discussion back in 2007 which addressed this issue: language inconsistencies, confusion for newbies, and possible short- and long-term solutions for Lua. one short-term solution is to use another value to represent ‘nil’ in your code – e.g., ‘false’ would work, as would something like this:
NIL = {} -- we create our own 'NIL' t={NIL,1,NIL} print(#t, table.maxn(t)) --=\> 3,3
http://lua-users.org/lists/lua-l/2007-07/msg00557.html
so that’s what i’ve discovered. take what you wish and choose your own path.
cheers,
dmc
ps, thanks @waltsir for the topic.