Semantic change of table length in Lua 5.5

67 views
Skip to first unread message

Sainan

unread,
Dec 24, 2025, 1:22:33 PM (4 days ago) Dec 24
to lu...@googlegroups.com
Hello, I realise I'm a bit 'behind' here, but I noticed the following change to tables in Lua 5.5 (specifically, 002beeebe79065e03dd9f531bee367e8459e3f64):

t = { nil, 2 }
print(#t) -- Lua 5.4: 2, Lua 5.5: 0
print(t[#t]) -- Lua 5.4: 2, Lua 5.5: nil

I didn't see it mentioned as an incompatibility, but I can imagine it can catch someone quite off-guard.

-- Sainan

Shmuel Zeigerman

unread,
Dec 24, 2025, 1:48:44 PM (4 days ago) Dec 24
to 'Sainan' via lua-l
On 24/12/2025 20:22, 'Sainan' via lua-l wrote:
I didn't see it mentioned as an incompatibility, but I can imagine it can catch someone quite off-guard.

This is not an incompatibility. The operator # is deterministic only for proper arrays.
See https://www.lua.org/manual/5.5/manual.html#3.4.7

-- 
Shmuel

Vaughan McAlley

unread,
8:10 AM (4 hours ago) 8:10 AM
to lu...@googlegroups.com
On Thu, 25 Dec 2025 at 05:22, 'Sainan' via lua-l <lu...@googlegroups.com> wrote:
Hello, I realise I'm a bit 'behind' here, but I noticed the following change to tables in Lua 5.5 (specifically, 002beeebe79065e03dd9f531bee367e8459e3f64):

    t = { nil, 2 }
    print(#t) -- Lua 5.4: 2, Lua 5.5: 0
    

t[3] = 3
print(#t) -- Lua 5.4: 0

So as always, no guarantees of length of holes with tables.

The code for determining table length is significantly different in Lua 5.5. This comment explains it:

/*
** Try to find a border in table 't'. (A 'border' is an integer index
** such that t[i] is present and t[i+1] is absent, or 0 if t[1] is absent,
** or 'maxinteger' if t[maxinteger] is present.)
** If there is an array part, try to find a border there. First try
** to find it in the vicinity of the previous result (hint), to handle
** cases like 't[#t + 1] = val' or 't[#t] = nil', that move the border
** by one entry. Otherwise, do a binary search to find the border.
** If there is no array part, or its last element is non empty, the
** border may be in the hash part.
*/

So now the table length will be zero if t[1] is nil.

Vaughan

Reply all
Reply to author
Forward
0 new messages