I'm trying to get the length of "table" to use as a max a randomizer
local message = {}
message[1] = "one"
message[2] = "two"
message[3] = "three"
local numberOfMessages = table.getsize(message) --returns the number 4
i guess i can subtract 1 when i use it but why does this happen?
I read the docs
[f] table.getsize(table)
Returns the size of the given table as a multiple values ( arrayCount , hashCount ).
What does it mean when it says it returns multiple values? is it coming back as an array?
I tried to use numberOfMessages.arrayCount and numberOfMessages.hashCount to try to get these values
Lua "multiple value" returns are weird. They work as follows, assigned to whatever two variables you choose:
local myArrayCount
local myHashCount
myArrayCount, myHashcount = table.getsize(myTable)
As for the two parts, Lua tables have integer keys (like you might expect from an array) which you can either assign the way you have done, or as follows:
local message = {"one", "two", "three"}
That's the "array" part.
But Lua tables can also contain named keys like this:
That's the "hash" part. (And you can't predict what order those will be stored at—the order is practically random—so don't try to access them by iterating through [integer] keys. Use message.startMessage or message[startMessage]. )
There's even more to Lua tables than that... they are still strange to me, but sometimes super useful! You can even nest tables inside tables.
and when i make 6 it makes an arrayCount of 8 total bonkers, i used table.create to explicit set the size and that works but kinda defeats the purpose if i have to know how many are in it to iterate through it.
I've had success with simply #message... but my tables are hard-coded data and don't change, so I could count them by hand if I wanted to bother.
Apparently the only reliable way to get the size of a table is to iterate it and increment a counter. But luckily you can iterate without knowing the size:
for index, value in ipairs(message) do
print(index, value)
end
That's for numeric indices. For named keys you'd use pairs() instead of ipairs().
Lua is still strange to me, including tables starting at 1 instead of 0... but these quirks do have their benefits!
It's likely called hash count as the non integer keys are stored in some kind of hash table behind the scenes. A hash function basically converts some sorting-unfriendly value like a string or object into a uniformly random number. A hash table then uses that value as a key to store the data. They are very good at efficiently storing and retrieving data and often used for storing strings or objects. Wikipedia article on them
As I recall, we added table.getsize() for Shaun Inman back when he was fixing performance problems in Crankin' and Ratcheteer, before he gave up on Lua with its automatic memory management and ported them to C. The returned values were only ever intended to be used as arguments to the table.create() function. I think what happened with the docs is we used to have those functions paired but they got split up when we reformatted Inside Playdate around the time we released the SDK. I'll file an issue to explain that better there. Thanks for pointing this out!
Just discovered this topic and think I could give a bit of extra context in case someone stumbles on this in the future: The getsize seems to be returning the allocated or "reserved" space for the table, not the number of entries that are currently in use. I found a good explanation of how tables work on page 19 of this PDF: Lua Performance Tips. It specifically explains why the arrayCount goes from 2 to 4 to 8, rather than giving you the 2, 3, 4 you were expecting.
In your case, you are using the array part of the table (i.e. your keys are positive integers), so you should be able to use #numberOfMessages to count the length as well. Be aware that this operator only works correctly for continuous sequences, which will usually be the case, but for a table like { "one", "two", "three", nil, "five" } the count would be reported as 3 and not 4.
For non-integer keys (that are part of the hash part of the table), you'll indeed have to manually count the entries using pairs().
n.b. The "object" in JavaScript is also implemented as a hashmap. My guess is that since a Lua table is a bit of a mix of 2 datatypes, they choose to be more explicit with their naming.
Thank you so much for sharing this, it helps a lot.
I was making a simple Snake game and noticed sometimes when I checked the length of how many segments the snake has, it'd report strange values. My code was using table.getsize. I made a simple reproducible example:
t = { }
function playdate.update()
if playdate.buttonJustPressed(playdate.kButtonA) then
table.insert(t, { gridX = 18 })
end
playdate.graphics.clear()
-- incorrect way:
playdate.graphics.drawText("getsize: " .. table.getsize(t), 40, 40)
-- correct way:
-- playdate.graphics.drawText("#: " .. #t, 40, 40)
end
Here are the results with table.getsize (you can see it jump all over the place).
It's a bit surprising that this is the behavior, as it seems quite bug-laden. It's pretty common to want to get the length of an array in a game, and table.getsize is what I found in Inside Playdate and thought I should use.
The docs currently in Inside Playdate say:
Returns the size of the given table as multiple values (arrayCount, hashCount).
I think it'd be more helpful if it called out that arrayCount is the allocated size and to use # to get the correct array length. Something like:
Returns the size of the given table as multiple values (arrayCount, hashCount). arrayCount is the allocated size of the array and may not always be accurate to how many items are present. Use # to get the actual length of the array.
@dave would it be possible to update the documentation with something like what Brett was talking about or:
Returns the size of the allocated memory (arrayCount, hashCount).
NOTE: values are different from the length of the array
Use Lua's built in # symbol like: #tableInQuestion to get the how many elements are in the array.
Just wanting to help people avoid confusion and save them time.