As a Roblox developer, it is currently too hard to understand why this code does what it does:
print(#{1, 2, 3, nil, 5, 6, 7, 8, 9, nil}) -- prints 9
print(#{1, 2, 3, nil, 5, 6, 7, 8, nil}) -- prints 3
print(#{1, nil, 3, 4, 5, 6, 7, 8, nil}) -- prints 8
The length of a lua table depends on the location of nil values inside the table. According to the Lua manual, this behavior is actually undefined. From the manual:
“it may consider any such nil value as the end of the array”
It doesn’t say which nil value will be considered the end of the table. Hence, the length of these tables is unpredictable.
Not convinced? Look at the following example:
local arr = table.create(1000, "Hello!")
for i = 1, #arr do
if i % 2 == 0 then
arr[i] = nil
end
end
print(#arr)
Every second element is nil. Guess what the code prints:
Answer: 187
This is obviously a meaningless and unpredictable result.
If Roblox is able to address this issue, it would improve my development experience because I wouldn’t have to spend hours debugging code that should work.
In any other programming language (except assembly), assigning array elements would not effect the length of the array. Lua is truly unique in this one. This behavior is impossible to predict and detrimental to development.
Here is another example of unintuitive behavior:
local arr = table.create(1000) -- Allocate 1000 elements
print(#arr) -- Prints 0 (where'd they go?)
Another example:
local arr = {nil, "ImportantInformation", nil}
for _, val in ipairs(arr) do
print(val) -- Never gets executed
end
Here is a reasonable example of a script that should work, but doesn’t:
-- Return an array of players on the given team
function getPlayersOnTeam(teamName)
local players = game.Players:GetChildren()
for i = 1, #players do
if players[i].Team.Name ~= teamName then
players[i] = nil
end
end
return players
end
-- Do something with each team member
local teamMembers = getPlayersOnTeam("Green Team")
for i = 1, #teamMembers do
if teamMembers[i] then
doWhateverWidthThisTeamMember()
end
end
I’m not saying that the above code can’t be rewritten in a way that works, I’m saying that any logical programmer would expect it to work, but it doesn’t.
I’m sure nobody relies on this confusing behavior. I hope that in the new Luau runtime, this unpredictable table behavior is eliminated to improve the consistency and intuition of the programming language.