Tables are the primary composite data structure in the Lua programming language. They are used as containers, especially sequences (with consecutive numeric indexes starting from 1) and mappings (also known as associative arrays, dictionaries, or hashtables). Tables can be used as general purpose objects, and when combined with metatables (see Lua reference) can implement object-oriented concepts such as inheritance. PICO-8 includes several built-in functions for using tables.
Mappings[]
Fundamentally, tables are mappings of keys to values. Key-value pairs are unordered. You can construct a new mapping using curly brackets. For example:
x = {a=1, b=2, c="hello"}
Values can be accessed using bracket notation, where the key is an expression (tbl["key"]
).
print(x["a"]) -- 1 x["a"] = 99 print(x["a"]) -- 99
If the key is a string using the characters of a Lua identifier (letters, numbers, underscore, and begins with a letter), then the value can also be accessed using property notation (tbl.key
).
print(x.b) -- 2 x.b = 88 print(x.b) -- 88
Accessing an unset key returns nil
.
if x.d == nil then print("x.d is nil") end
PICO-8 provides the built-in pairs(), which iterates over all key-value pairs in a table.
for k,v in pairs(x) do print(k.." = "..v) end
Sequences[]
A sequence is a table with a contiguous series of numeric keys, starting with 1, each of which has a non-nil value. Lua offers special syntax and features so that sequences behave somewhat like lists or arrays in other languages.
-- constructor syntax for sequences p = {2, 3, 5, 7, 11} print(p[1]) -- should print "2" print(p[5]) -- should print "11" if p[0] == nil then print("p[0] is nil") -- should print "p[0] is nil" end -- the sequence length operator print(#p) -- should print "5" for i=1,#p do print("p["..i.."] = "..p[i]) end
No key in the middle of a sequence should ever be set/cleared to nil. Only contiguous keys at the end of the sequence should be cleared, in reverse order. Setting the final key(s) to nil is okay, because Lua will understand that they are being removed, and it will therefore reduce the length by by that many. Similarly, setting the next key to something non-nil will extend the sequence by 1, and this should always be done in forward order.
-- same sequence as last time p = {2, 3, 5, 7, 11} print(#p) -- should print "5" -- add three more elements to the sequence p[#p+1]=13 p[#p+1]=17 p[#p+1]=19 print(#p) -- should print "8" -- shorten the sequence by 2 p[#p]=nil p[#p]=nil print(#p) -- should print "6"
Caution: If a key other than the final key is set to nil, or a key other than the next after the sequence is set to non-nil, the result is undefined. In some cases, Lua will recognize the change and will adjust the sequence. However, in others, it will not. There seems to be no consistent behavior. To avoid this problem, only make changes at the end of a sequence.
Note that a table containing a sequence is also allowed to have other keys. However, those keys are not considered part of the sequence. The sequence part only consists of all numbered keys starting from 1 ascending up to the last key with a non-nil value. The # operator will only count those keys, ignoring any others present.
Built-ins for sequences[]
PICO-8 provides several built-ins that operate on sequences:
- all(), which iterates over elements in the sequence in a table.
tbl = {2, 3, 5, 7, 11} for v in all(tbl) do print(v) end
- add() appends a value to the end of a sequence.
- del() removes the first element of the sequence that equals a given value, shifting all remaining elements down by one index to keep the sequence intact.
- foreach() calls a given function for each element in the sequence, passing the element as the sole argument to the function.
- unpack() returns sequence values