User Tools

Site Tools


lgscript:lua_tables

Tables

Composite data can be stored in a table. Tables are objects, so the value is passed by reference when variables are assigned to or when they are used as parameters to functions.

A table can store any value, including other tables. The values are accessed using indexes. An index can be any value except nil. Two indexes refer to the same storage in the table if they are equal. Integer and real numbers will equate to each other, but a number and a string of the same number are different. Objects only equate if they are both references to the same value. Tables do not consider metamethods when comparing objects.

A table index with a nil value is equivalent to a non-existent index. Indexes which have not been created will return nil when read.

The most efficient way to store values in a table is with consecutive integer indexes (or integer-valued real numbers). The first index of the table is 1. The number of values stored in the table is equal to the highest index. This can be determined with the # operator.

More specifically, the “length” operator finds an integer index in the table such that the next consecutive integer index is not assigned a value. When all the used indexes of the table are consecutive, this is the same as the end of the table. If the used indexes are not consecutive, then the table is said to have a “hole”. The length operator is not reliable when used on a table with holes. Although such tables can be useful in other ways.

A table with consecutive integer indexes is called an “array”. If you use indexes that are not consecutive, or are less than 1, or are not integers, then the it is an “associative table”. Associative indexes are referred to as “keys”. An associative table is a collection of key-value pairs. From this definition you can see that an array is also a type of associative table.

Tables are created with the constructor operators { and }. A table index is accessed with the subscript operators [ and ].

a = {}
a[1] = "alpha"
a[2] = "beta"
a[3] = "gamma"
print(#a, a[1], a[3], a[5])    -- 3, alpha, gamma, nil
a[3] = nil
a['x'] = "chi"
print(#a, a.x)         -- 2, chi

The . operator is a shorthand for accessing keys. The key has to be a string and the string value has to be a valid name. (Start with a letter or underscore, and contain only letters, digits, or underscores.) Typing a.x is the same as a["x"].

A list of expressions can be placed between the curly braces of a table constructor. The values of the list will be used to fill the table. The list of values is treated similarly to an assignment list for variables or function parameters. This means that a function call which returns multiple values will be reduced to a single value if it is not the last expression in the table constructor, and will use all of its values if it is at the end of the list. Unlike other lists, a table constructor allows the expressions to be separated with semi-colons as well as commas. Also, the last expression in the list can be followed by a comma or semi-colon and it will simply be ignored.

As well as the values, indexes can be given in a table constructor. If the index is a name that can be used with the . operator, then you only need to type the name and an equals sign, like you are assigning a variable. Otherwise, put the index in square braces like a subscript.

a = { "alpha", "beta", [4] = "delta"; x = "chi" }
obj = {}
function obj.add(self, value)
    self[#self+1] = value
end
function obj:append(value)
    self[#self+1] = value
end

This example shows how a dotted name can be used to create functions inside a table. The indexes add and append are added to the table and the values are functions. The second form, using a colon instead of a dot, is a special way to define the function as a “method”. A function that is a method has an extra hidden variable in the parameter list named self. The first functions shows how this looks when written explicitly.

The colon is also used when calling a method. To call the append method from the example, you type obj:append(5), which is the same as typing obj:append(obj, 5). This can be useful if you are using an expression to get the table, instead of a variable. The table object is retrieved once and only a reference needs to be copied to the parameter list. When a table is nested, only the last dot is changed to a colon to form a method.

The example functions assign the value to the end of the array part of the table. The expression in the subscript is a common way of getting the next free index in an array. For any table A, the expression #A+1 is guaranteed to be an unassigned index.

Like with strings, there is a shortcut for calling a function using a table as the parameter. If you use the table constructor braces instead of parenthesis when calling a function, the table that is created is passed to the function as the only parameter. This is a way to create a function that uses named parameters without having to create a long list of parameters.

function color(param)
    local red = param.red or 0
    local green = param.green or 0
    local blue = param.blue or 0
    return ((blue % 256) * 0x10000) + ((green % 256) * 0x100) + (red % 256)
end
-- turquoise
c = color{blue=200, green=180}
lgscript/lua_tables.txt · Last modified: 2009/08/27 22:19 by telliamed