This first edition was written for Lua 5.0. While still largely relevant for later versions, there are some differences.
The fourth edition targets Lua 5.3 and is available at Amazon and other bookstores.
By buying the book, you also help to support the Lua project.

19.1 – Array Size

Frequently, in Lua, we assume that an array ends just before its first nil element. This convention has one drawback: We cannot have a nil inside an array. For several applications this restriction is not a hindrance, such as when all elements in the array have a fixed type. But sometimes we must allow nils inside an array. In such cases, we need a method to keep an explicit size for an array.

The table library defines two functions to manipulate array sizes: getn, which returns the size of an array, and setn, which sets the size of an array. As we saw earlier, there are two methods to associate an attribute to a table: Either we store the attribute in a field of the table, or we use a separate (weak) table to do the association. Both methods have pros and cons; for that reason, the table library uses both.

Usually, a call table.setn(t, n) associates t with n in an internal (weak) table and a call table.getn(t) retrieves the value associated with t in that internal table. However, if the table t has a field "n" with a numeric value, setn updates this value and getn returns it. The getn function still has a last option: If it cannot get an array size with any of those options, it uses the naive approach: to traverse the array looking for its first nil element. So, you can always use table.getn(t) in an array and get a reasonable result. See the examples:

    print(table.getn{10,2,4})          --> 3
    print(table.getn{10,2,nil})        --> 2
    print(table.getn{10,2,nil; n=3})   --> 3
    print(table.getn{n=1000})          --> 1000
    a = {}
    print(table.getn(a))               --> 0
    table.setn(a, 10000)
    print(table.getn(a))               --> 10000
    a = {n=10}
    print(table.getn(a))               --> 10
    table.setn(a, 10000)
    print(table.getn(a))               --> 10000

By default, setn and getn use the internal table to store a size. This is the cleanest option, as it does not pollute the array with an extra element. However, the n-field option has some advantages too. The Lua core uses this option to set the size of the arg array, in functions with variable number of arguments; because the core cannot depend on a library, it cannot use setn. Another advantage of this option is that we can set the size of an array directly in its constructor, as we saw in the examples.

It is a good practice to use both setn and getn to manipulate array sizes, even when you know that the size is at field n. All functions from the table library (sort, concat, insert, etc.) follow this practice. Actually, the possibility of setn to change the value of the field n is provided only for compatibility with older versions of Lua. This behavior may change in future versions of the language. To play safe, do not assume this behavior. Always use getn to get a size set by setn.