Lua is an extension programming language designed to support general procedural programming with data description facilities. Lua is intended to be used as a powerful, lightweight scripting language for any program that needs one.
Corona uses Lua version 5.1.3. Please see the Lua 5.1 Reference Manual for more details.
Names (also called identifiers) in Lua can be any string of letters, digits, and underscores, not beginning with a digit. This coincides with the definition of names in most languages. The definition of “letter” depends on the current locale: any character considered alphabetic by the current locale can be used in an identifier. Identifiers are used to name variables and table fields.
The following keywords are reserved and cannot be used as names:
and break do else elseif end false for function if in local nil not or repeat return then true until while
The following strings denote other tokens:
+ - * / % ^ # == ~= <= >= < > = ( ) { } [ ] ; : , . .. ...
Lua is a case-sensitive language: and
is a reserved word, but And
and AND
are two different, valid names. As a convention, names starting with an underscore followed by uppercase letters _VERSION
)
A comment starts with a double hyphen (--
) anywhere outside a string. They run until the end of the line. You can comment out a full block of code by surrounding it with --[[
and --]]
. To uncomment the same block, simply add another hyphen to the first enclosure, as in ---[[
.
-- Single line commented out --[[ Entire block commented out print( 10 ) print( 15 ) --]]
A numerical constant can be written with an optional decimal part and an optional decimal exponent. Lua also accepts integer hexadecimal constants, by prefixing them with 0x
. Examples of valid numerical constants are:
3 3.0 3.1416 314.16e-2 0.31416E1 0xff 0x56
Lua is a dynamically typed language. This means that variables do not have types; only values do. There are no type definitions in the language. All values carry their own type.
All values in Lua are first-class values. This means that all values can be stored in variables, passed as arguments to other functions, and returned as results.
The basic types you should be concerned with are:
nil — the type of the value nil
, whose main property is to be different from any other value; it usually represents the absence of a useful value.
boolean — the type of the values false
and true
. Both nil
and false
make a condition false; any other value makes it true.
number — represents real (double-precision floating-point) numbers.
string — represents arrays of characters. Lua is
function — see Functions for more information.
table — the sole data structuring mechanism in Lua. See Tables for more information.
Lua provides automatic conversion between string and number values at run time. Any arithmetic operation applied to a string tries to convert this string to a number, following the usual conversion rules. Conversely, whenever a number is used where a string is expected, the number is converted to a string, in a reasonable format. For complete control over how numbers are converted to strings, use the string.format function from the string library.
Tables are the sole data structuring mechanism in Lua. They implement associative arrays, meaning that arrays can be indexed not only with numbers, but with any value except nil
. Tables can be heterogeneous and they can contain values of all types except nil
.
To represent records (properties), Lua uses the field name as an index. The language supports this representation by providing a.name
as syntactic sugar for a["name"]
.
Like indices, the value of a table field can be of any type except nil
. In particular, because functions are
Tables are objects: variables do not actually contain these values, only references to them. Assignment, parameter passing, and function returns always manipulate references to such values; these operations do not imply any kind of copy.
The table constructor is written using braces (curly brackets) as in {}
.
t = {} -- Create a table k = "x" t[k] = 3.14 -- New table entry with key = "x" and value = 3.14 print( t[k] ) --> 3.14 print( t["x"] ) --> 3.14 print( t.x ) --> 3.14 t[2] = "foo" -- New table entry with key = 2 and value = "foo" print( t[2] ) --> "foo"
In the above example, the entry with field name "x"
was accessed in two ways: as a property using the dot operator t.x
and as an array index using t["x"]
.
A common mistake is to confuse t.x
with t[x]
. The first is equivalent to t["x"]
: a table indexed by the string "x"
. The second is a table indexed by the value of variable x
.
Many Corona APIs return objects. You can manipulate the documented properties of these objects just like you would for table properties. You can even add your own properties provided you do not prefix any of your custom properties with an underscore, as in t._custom = 10
Variables are places that store values. There are three kinds of variables in Lua: global, local, and table fields (properties). Any nil
by default.
Global variables do not need declarations. You simply assign a value to one to create it:
print( s ) --> nil s = "One million dollars" print( s ) --> One million dollars
Global variables live as long as your application is running. You can delete a global variable by assigning nil
to it. At this point, the global variable behaves as if it were never initialized.
s = nil print( s ) --> nil
Local variables are declared using the local statement:
x = 1 -- Global variable local y = 10 -- Local variable
Unlike global variables, local variables are visible only in the block where they are declared. The scope of the local variable begins after the declaration and ends at the end of the block.
a = 10 local i = 1 while ( i <= 10 ) do local a = i*i -- Different variable "a", local to this "while" block print( a ) --> 1, 4, 9, 16, 25, ... i = i + 1 end print( a ) --> 10 (the global "a")
Table fields are just the elements of the table themselves. You index into the array to assign the values to a field.
t = { foo="hello" } -- Create table with a single property "foo" print( t.foo ) --> "hello" t.foo = "bye" -- Assign a new value to property "foo" print( t.foo ) --> "bye" t.bar = 10 -- Create a new property named "bar" print( t.bar ) --> 10 print( t["bar"] ) --> 10
Lua supports the usual binary arithmetic operators:
Operator | Purpose |
---|---|
+ |
addition |
- |
subtraction |
* |
multiplication |
/ |
division |
% |
modulo |
^ |
exponentiation |
It also supports the unary -
(negation).
If the operands are numbers or strings that can be converted to numbers, all operations have the usual meaning. Exponentiation works for any exponent. For instance, x^(-0.5)
computes the inverse of the square root of x
.
Modulo is defined as: a % b == a - math.floor(a/b)*b
The relational operators in Lua are:
Operator | Purpose |
---|---|
== |
equal to |
~= |
not equal to |
< |
less than |
> |
greater than |
<= |
less than or equal to |
>= |
greater than or equal to |
These operators always result in true
or false
.
Equality (==
) first compares the type of its operands. If the types are different, then the result is false
. Otherwise, the values of the operands are compared.
Numbers and strings are compared in the usual way. Objects are compared by reference: two objects are considered equal only if they are the same object. Every time you create a new object, this object is different from any previously existing object.
The automatic conversion rules do not apply to equality comparisons. Thus, "0" == 0
false
.
The logical operators in Lua are and
, or
, and not
. All logical operators consider both false
and nil
as false and anything else as true.
and — the conjunction operator and
returns its first argument if this value is false
or nil
; otherwise, and
returns its second argument.
or — the disjunction operator or
returns its first argument if this value is different from nil
and false
; otherwise, or
returns its second argument.
not — the negation operator not
always returns false
or true
.
Both and
and or
use shortcut evaluation — the second operand is evaluated only if necessary.
10 or 20 --> 10 10 or error() --> 10 nil or "a" --> "a" nil and 10 --> nil false and error() --> false false and nil --> false false or nil --> nil 10 and 20 --> 20
The string concatenation operator in Lua is denoted by two dots (..
). If both operands are strings or numbers, then they are converted to strings according to the conversion rules mentioned above.
local s = "foo".."10"
The length operator is denoted by the unary operator #
. The length of a string is its number of bytes — the usual meaning of string length when each character is one byte.
The length of a table t
is defined to be any integer index n
such that t[n]
is not nil
and t[n+1]
is nil
; moreover, if t[1]
is nil
, n
can be zero. For a regular array, with nil
n
, its length is exactly that n
, the index of its last value. If the array has “holes” nil
valuesnil
values)#t
can be any of the indices that directly precedes a nil
value. Thus, it may consider any such nil
value as the end of the array.
Operator precedence in Lua follows the list below, from lower to higher priority:
or
and
<
, >
, <=
, >=
, ~=
, ==
..
+
, -
*
, /
, %
not
, #
, -
(unary)^
As usual, you can use parentheses to change the precedences of an expression. The concatenation (..
) and exponentiation (^
) operators are right associative. All other binary operators are left associative.
Plain functions are just as expected: you provide arguments as input
The following are common methods to declare a function:
local function f () --body end local f = function() --body end function f () --body end f = function () --body end
Functions can be variables, so a table can store them as properties. This allows for very flexible uses of a table. It can be used to logically group a family of functions into a table, for example the math
library. In this case, to calculate the sine of 100, you would write math.sin(100)
. Here, math
is merely a table, and the property sin
is the actual function.
Objects in Lua are represented by tables. Display objects and the global Runtime object are all objects. Like the math
library, these objects similarly store object methods (instance methods) as properties. One key difference, however, is syntax. You need to tell Lua that you intend this function to be called as an object method, not just a plain function. To do so, you need to use the colon (:
) operator instead of the dot operator. This may be different from other languages. Compare the syntax of Javascript and Lua:
Javascript | Lua |
---|---|
object.translate( 10, 10 ); |
object:translate( 10, 10 ) |
Lua is a lexically scoped language. The scope of variables begins at the first statement after their declaration and lasts until the end of the innermost block that includes the declaration.
x = 10 -- Global variable do -- New block local x = x -- New "x" with value 10 print(x) --> 10 x = x+1 do -- Another block local x = x+1 -- Another "x" print(x) --> 12 end print(x) --> 11 end print(x) --> 10 (the global one)
Notice that, in a declaration like local x = x
x
being declared is not in scope yet, and so the second x
refers to the outside variable.
Because of the lexical scoping rules, local variables can be freely accessed by functions defined inside their scope. A local variable used by an inner function is called an upvalue, or external local variable, inside the inner function.
Notice that each execution of a local
statement defines new local variables:
a = {} local x = 20 for i = 1, 10 do local y = 0 a[i] = function () y = y+1; return x+y end end
The loop creates ten closures (ten instances of the anonymous function). Each of these closures uses a different y
variable, while all of them share the same x
.
Mobile devices in particular have limited memory available for use, so care must be taken to ensure that the total memory footprint of your application is kept to a minimum.
Lua performs automatic memory management. This means that you don’t have to worry about allocating memory for new objects. Nor do you need to explicitly free memory when the objects are no longer needed. Lua manages memory automatically by running a garbage collector from time to time to collect all “dead” objects (objects that are no longer accessible from Lua). All memory used by Lua is subject to automatic management. However, it is up to you to tell Lua what to consider garbage. For example, anything stored in a global variable is not considered garbage, even if your application never uses it again. Similarly, anything stored in a table or array will not be considered garbage if that table/array cannot be removed by the garbage collector, even if the stored variable/object was initially declared in the local scope. In both cases, it is up to you to assign nil
to these positions. This ensures that their corresponding memory will not be locked and can be freed by the garbage collector.
Display object require an additional step. You must first remove the object from the display hierarchy using object:removeSelf()
or display.remove( object )
nil
.
myObject:removeSelf() -- OR... display.remove( myObject ) myObject = nil
Some differences in syntax between Lua and other languages are worth noting because they can help prevent compiler errors:
semicolons — trailing semicolon at the end of each statement (effectively a line of code) are optional in Lua.
braces — You may be accustomed to using { }
do
and end
. Braces in Lua are interpreted as table constructors.
if - then - else — if you come from C, Java, Javascript, etc., a common mistake you’ll make in writing if
and elseif
statements is forgetting to append then
to the end of the if/elseif
test conditions. Another common mistake is inadvertently using else if
(with a space) when Lua expects elseif
.
arrays — in Lua, arrays are 1-based. Technically, you can index into an array starting with 0
. However, Lua and Corona APIs assume that the first element of a table t
is t[1]
, not t[0]
.
multiple return values — an unconventional but useful feature in Lua is the ability of a function to return more than one result.
multiple assignment — multiple assignments offer a convenient way to swap values. The statement x,y = y,x
x
for y
and vice versa.
ternary operator (? :
) — Lua does not offer the equivalent to the C ternary operator a?b:c
. The Lua idiom (a and b) or c
b
is not false. For example, the Lua equivalent to max = (x>y?x:y)
max = ( x>y and x or y)
The basic Lua library provides several core functions. For security reasons, the dofile()
, load()
, and loadfile()
functions are not available in Corona. loadstring()
is supported.
See the (globals) API reference for the complete list available to you.
Content in this guide is cited from the Lua 5.1 Reference Manual, freely available under the terms of the Lua license.