Log In  

Hey.. Can someone please explain what's going on here for me?

Here's a test cart that prints the content of table 'x' (a table with the first 16 offsets set to 1 by default) and the value of '#x'..

LEFT/RIGHT changes the offset of table 'x'
X sets the offset to 1 / Z (O) sets the offset to nil

Cart #42605 | 2017-07-18 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
2

If I set certain values to nil in a table, then len will start returning 0 even though there are still items inside the table. This seems to happen when a 'certain' number of items, including the item in offset=1 are set to nil, and then offset 0 or offset -1 are set to nil:

This doesn't seem entirely consistent.. Here, if I start at offset 7 instead of offset 13, then len still returns the highest index with non-nil data. Even if I'm setting offset 0 or offset -1 to nil:

Is this a bug or just a quirk of lua?
If so, does anyone have a list of rules for this behavior so I can design around it?

P#42603 2017-07-18 15:47 ( Edited 2017-07-19 15:49)

:: Felice

I'm pretty sure lua only recalculates length when you nil-ifiy the last entry in an array:

> x={1,2,3,4,5}
> ?#x
5
> x[2]=nil
> x[4]=nil
> ?#x
5
> x[5]=nil
> ?#x
1

Worse, if you note above that if I first clear entries 2,4 giving {1,nil,3,nil,5}, and then clear 5 as well, conceptually giving {1,nil,3}, #x comes back as 1, not 2, because the recalc only counts from the first entry to the first nil.

Basically, if you're going to do sparse arrays, just don't rely on # at all. It's a headache waiting to happen.

P#42606 2017-07-18 16:04 ( Edited 2017-07-18 20:05)
:: enargy

Darn! :p Thank you for checking it out!

Using 'del(x,value)' appears to shift indices around so that this isn't an issue (since there are no gaps). It's important for me that indices can be mapped consistently across different tables though, so..

I guess I can change things to use some other value like a '-1' instead of nil. And then do all checks for that value instead. I'm pretty sure most of the code is currently 'if x[i]==nil' and not 'if not x[i]' so maybe using this method won't be such a big deal.

P#42607 2017-07-18 16:18 ( Edited 2017-07-18 20:18)
:: Felice

Can you just use the pairs() iterator instead?

for key,value in pairs(table) do
  print("table["..key.."]="..value)
end

It'll always work, regardless of gaps. Order isn't guaranteed, since you're iterating over an unordered hash table, but you'll hit every valid entry at least and you can leave indices alone when removing elements.

P#42611 2017-07-18 20:45 ( Edited 2017-07-19 00:45)
:: helado

here's the relevant part of another answer i posted here:

for tables where integer-valued keys don't form a contiguous sequence starting at 1, the result of # is implementation-defined, so it's often not helpful for those. # also isn't useful for finding non-integer keys. more information on #'s behavior is in the lua manual.

P#42613 2017-07-19 00:23 ( Edited 2017-07-19 04:23)
:: enargy

@Felice: Oo, pairs would have worked.. but I already ended up going with the '-1' thing and just modifying some code.

The asset editor I'm working on is almost complete but I'll look at using that technique in other projects to simplify some code.

@helado: Thank you for the additional info. I'm used to python's ordered lists and I'm finding that lua is structured a little differently than I would expect from that. Think I'm getting the hang of it though :)

P#42620 2017-07-19 11:49 ( Edited 2017-07-19 15:49)

[Please log in to post a comment]

Follow Lexaloffle:        
Generated 2020-02-29 14:18 | 0.026s | 2097k | Q:34