Download as pdf or txt
Download as pdf or txt
You are on page 1of 4

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.

Programming in Lua
Part I. The Language
Chapter 3. Expressions

3.6 – Table Constructors


Constructors are expressions that create and
initialize tables.
They are a
distinctive feature of Lua
and one of its most useful and versatile
mechanisms.

The simplest constructor is the empty constructor,


{}, which creates an empty
table;
we saw it before.
Constructors also initialize arrays
(called also
sequences or lists).
For instance, the statement

days = {"Sunday", "Monday", "Tuesday", "Wednesday",

"Thursday", "Friday", "Saturday"}

will initialize days[1] with the string "Sunday"


(the first element has always
index 1, not 0),
days[2] with "Monday",
and so on:

print(days[4]) --> Wednesday

Constructors do not need to use only constant expressions.


We can use any
kind of expression for the value of each element.
For instance, we can build a
short sine table as

tab = {sin(1), sin(2), sin(3), sin(4),

sin(5), sin(6), sin(7), sin(8)}

To initialize a table to be used as a record,


Lua offers the following syntax:

a = {x=0, y=0}

which is equivalent to

a = {}; a.x=0; a.y=0

No matter what constructor we use to create a table,


we can always add and
remove other fields of any type to it:

w = {x=0, y=0, label="console"}

x = {sin(0), sin(1), sin(2)}

w[1] = "another field"

x.f = w

print(w["x"]) --> 0

print(w[1]) --> another field

print(x.f[1]) --> another field

w.x = nil -- remove field "x"

That is, all tables are created equal;


constructors only affect their initialization.

Every time Lua evaluates a constructor,


it creates and initializes a new table.
Consequently, we can use tables to implement linked lists:

list = nil

for line in io.lines() do

list = {next=list, value=line}

end

This code reads lines from the standard input


and stores them in a linked list,
in reverse order.
Each node in the list is a table with two fields:
value, with
the line contents,
and next, with a reference to the next node.
The following
code prints the list contents:

l = list

while l do

print(l.value)

l = l.next

end

(Because we implemented our list as a stack,


the lines will be printed in
reverse order.)
Although instructive,
we hardly use the above implementation
in real Lua programs;
lists are better implemented as arrays,
as we will see in
Chapter 11.

We can mix record-style and list-style


initializations in the same constructor:

polyline = {color="blue", thickness=2, npoints=4,

{x=0, y=0},

{x=-10, y=0},

{x=-10, y=1},

{x=0, y=1}

The above example also illustrates how we can nest constructors


to represent
more complex data structures.
Each of the elements polyline[1], ...,
polyline[4]
is a table representing a record:

print(polyline[2].x) --> -10

Those two constructor forms have their limitations.


For instance,
you cannot
initialize fields with negative indices,
or with string indices that are not
proper identifiers.
For such needs, there is another, more general, format.
In
this format,
we explicitly write the index to be initialized as an expression,
between square brackets:

opnames = {["+"] = "add", ["-"] = "sub",

["*"] = "mul", ["/"] = "div"}

i = 20; s = "-"

a = {[i+0] = s, [i+1] = s..s, [i+2] = s..s..s}

print(opnames[s]) --> sub

print(a[22]) --> ---

That syntax is more cumbersome, but more flexible too:


Both the list-style and
the record-style forms are special
cases of this more general one.
The
constructor

{x=0, y=0}

is equivalent to

{["x"]=0, ["y"]=0}

and the constructor

{"red", "green", "blue"}

is equivalent to

{[1]="red", [2]="green", [3]="blue"}

For those that really want their arrays starting at 0,


it is not difficult to write
the following:

days = {[0]="Sunday", "Monday", "Tuesday", "Wednesday",

"Thursday", "Friday", "Saturday"}

Now, the first value, "Sunday", is at index 0.


That zero does not affect the other
fields,
but "Monday" naturally goes to index 1,
because it is the first list value
in the constructor;
the other values follow it.
Despite this facility,
I do not
recommend the use of arrays starting at 0 in Lua.
Remember that most
functions assume that
arrays start at index 1,
and therefore will not handle
such arrays correctly.

You can always put a comma after the last entry.


These trailing commas are
optional, but are always valid:

a = {[1]="red", [2]="green", [3]="blue",}

Such flexibility makes it easier to write programs that generate Lua tables,
because they do not need to handle the last element as a special case.
Finally, you can always use a semicolon instead of a comma in a constructor.
We usually reserve semicolons to delimit
different sections in a constructor,
for instance to separate its list part from its record part:

{x=10, y=45; "one", "two", "three"}

Copyright © 2003–2004 Roberto Ierusalimschy. All rights reserved.

You might also like