Log In  
Log In  

Hello!

I have just started to dive into Pico 8 and Lua. I've been working on building a simple animator for my game and have run into some strange issues with regard to tables.

I declare a table and later add to it like this:

a = {}
a.p = {x=1, y=2, z=3}

The function count(a) then returns 0. Additionally, all(a) and foreach(a, function) will not iterate overt the table. Strangely, I am still able to access the information. For example,

print(a.p.x)

will correctly print the number 1. If I declare the table explicitly

a = {p={x=1,y=2,z=3}}

I have no issues. I also don't have issues if I use add() to insert new table values. However, I need to utilize the associative array functionality of the table and to add and remove values at runtime, so neither of these solutions is sufficient.

The best fix I have found is to use pairs() instead of all(). For some reason, pairs() works properly regardless of how I add values to the table. This solves my problem, but the fact that I have no idea why leads me to believe that I have some serious misunderstanding of how Lua tables and/or the Pico 8 tables api works. I'm curious as to whether others have encountered this issue and would appreciate some feedback as to where my misunderstanding may lie.

P#60469 2018-12-31 20:22

A number of functions that work on tables operate on consecutive numeric indices starting at 1. So a loop over all(tbl), for instance, will run on tbl[1], tbl[2], tbl[3], and so on until it encounters one that isn't defined. It won't skip missing numbers, so if tbl has keys 1, 2, 3, and 7, it'll only get the first three.

P#60473 2018-12-31 23:41

Yes, you're trying to treat a non-sequence table as a sequence.

https://pico-8.wikia.com/wiki/Tables#Sequences

P#60480 2019-01-01 11:02
:: Felice

As an aside, I'm pretty sure count() is deprecated.

It's literally a function roughly like this, hidden behind the scenes:

function count(t)
  local i=0
  repeat i=i+1 until t[i]==nil
  return i-1
end

It's not exactly performant or robust.

If you want the count of a numerically-indexed array, use the # operator, which is fast, or if you want to count the elements of an arbitrarily-mapped table, use pairs() and count them yourself:

function tablesize(t)
  local c=0
  for k,v in pairs(t) do
    c+=1
  end
  return c
end
P#60487 2019-01-01 20:02 ( Edited 2019-01-02 02:16)
:: jhol

Thank you! I did not realize that the implementation of add() and all() rely on a sequence table, but that makes quite a bit of sense. Out of curiosity, how does the # operator work? I have been treating # and count() as interchangeable, and it seems that # relies on a sequence as well.

P#60491 2019-01-01 23:56

The operator # works by returning 0 if t[1]==nil, or by searching for an integer n such that t[n]!=nil and t[n+1]==nil.

If the integer indices in your table are continuous and start at 1, this will return the length of the array part. Otherwise, this may return the length of the array, but you will have surprises.

P#60500 2019-01-02 15:59 ( Edited 2019-01-02 15:59)
:: Felice

@samhocevar

Not exactly. The # operator returns a cached value for the sake of speed. Lua tries to keep it correct by recognizing things that would make it change, but you can definitely set up an array from 1 to 100 and then set array[50] to nil and #array will still say 100.

Here:

Sometimes it'll get it right if you set a bunch to nil, but not always. The only guaranteed change is when you set a[#a] to nil.

Mostly you should consider the # operator to return the index of the highest-known non-nil entry.

P#60541 2019-01-03 19:44 ( Edited 2019-01-03 19:46)

Yep, the manual says this:

"When t is a sequence, #t returns its only border, which corresponds to the intuitive notion of the length of the sequence. When t is not a sequence, #t can return any of its borders. (The exact one depends on details of the internal representation of the table, which in turn can depend on how the table was populated and the memory addresses of its non-numeric keys.)"

A "border" here is what's been mentioned earlier in the thread: A non-nil value followed by a nil value.

I basically tread # as "undefined" for non-sequences.

P#60546 2019-01-03 22:12 ( Edited 2019-01-03 22:13)

@Felice maybe you misread me? I said Lua finds an integer that satisfies the property (any integer it deems suitable, and 100 satisfies the property in your example). And if the array is well-formed, then it returns the size of the array.

P#60547 2019-01-03 22:20

[Please log in to post a comment]

About | Contact | Updates | Terms of Use
Follow Lexaloffle:        
Generated 2019-05-25 11:45 | 0.023s | 2097k | Q:28