BulletManager (performance argument)

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
raidho36
Party member
Posts: 2063
Joined: Mon Jun 17, 2013 12:00 pm

Re: BulletManager (performance argument)

Post by raidho36 »

It's actually the index of any element preceding a nil
That appears to be the case. But then "length" is a bad name as well because array could be longer than this value. So the only way to reliably iterate through array with holes is to use "pairs". Then again, it ignores holes and includes literal indices. Alternatively, you keep track of its real length elsewhere.
User avatar
pgimeno
Party member
Posts: 3639
Joined: Sun Oct 18, 2015 2:58 pm

Re: BulletManager (performance argument)

Post by pgimeno »

airstruck wrote:No, it isn't. It's actually the index of any element preceding a nil (which may or may not be the highest numbered integer indexed element). The manual says so in the first sentence of the paragraph explaining the behavior of the length operator on tables.
In further support of this, in LuaJIT:

Code: Select all

print(#{1, 2, nil, 4, 5}) -- prints 5
print(#{1, 2, 3, nil, 5}) -- prints 3
User avatar
airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: BulletManager (performance argument)

Post by airstruck »

raidho36 wrote:But then "length" is a bad name as well because array could be longer than this value.
Bad or not, that's still its name. If you have a better suggestion for a name, pitch it to the Lua authors. It would be confusing if users started calling it by something other than its name.

Also, an array can't be longer than this value if "length" in this context simply means the index of any non-nil element preceding a nil, and nothing more. The word can mean whatever the authors want it to mean; they probably just found it to be a good fit for that concept (I've never seen any better suggestions, anyway).
So the only way to reliably iterate through array with holes is to use "pairs". Then again, it ignores holes and includes literal indices.
And the order of iteration is not defined, and it won't JIT.
Alternatively, you keep track of its real length elsewhere.
Yeah, that's the usual approach to storing sparse arrays. Generally the "real" length is stored in the same table in a key named "n" (which has some historical precedent because of its special meaning to the deprecated/removed "table.getn" and "table.setn" functions).
pgimeno wrote:In further support of this, in LuaJIT:

Code: Select all

print(#{1, 2, nil, 4, 5}) -- prints 5
print(#{1, 2, 3, nil, 5}) -- prints 3
Right, and it's implementation-dependent; as I recall PUC Lua gives different results in at least one of those cases. Anyway, bottom line is # won't give predictable results on sparse arrays.
Last edited by airstruck on Sun Aug 28, 2016 8:13 pm, edited 1 time in total.
User avatar
raidho36
Party member
Posts: 2063
Joined: Mon Jun 17, 2013 12:00 pm

Re: BulletManager (performance argument)

Post by raidho36 »

pgimeno wrote: In further support of this, in LuaJIT:

Code: Select all

print(#{1, 2, nil, 4, 5}) -- prints 5
print(#{1, 2, 3, nil, 5}) -- prints 3
Furthermore

Code: Select all

foo = {1, 2, 3}
print(#foo) -- prints 3
foo[10] = 10
print(#foo) --prints 3 also
Now that I think of it, I believe I have an idea why it works like this. In LUA, tables consist of two parts: array part and hash part. Small integer keys go to array part, everything else goes to hash part. When space runs out, it doubles part's length, and to avoid unnecessary reallocation early on its pre-heated to 4 elements each. If you add an integer key outside of array part size and it decides it's not worth to resize it to fit new key, it puts it to hash part. At the same time, removing keys in the middle of it doesn't alters it's length. So I believe, length operator only returns largest key from array part. It's obviously not possible (feasible anyway) with hash part. Hence length is not necessarily largest integer (it could be in hash). In fact I'm pretty sure you can construct a table with nothing but integer keys with length 0 by making it put them all in hash part.

Code: Select all

print (#{ [1000] = 1, [1010] = 2, [1020] = 3 }) --prints 0
Post Reply

Who is online

Users browsing this forum: pgimeno and 4 guests