Lua/Tutorial
Wikibooks has a book about Lua Programming |
Getting started
[edit]This tutorial aims to be accessible to all manner of programmers. Experienced users will read at great speed and beginners can digest the text more slowly; both can take advantage of the examples to clarify. It is thought that learning by example is the best form of learning. Please note that this tutorial assumes you are using Lua version 5.1.
You can use the live demo to play with Lua. You could also install Lua locally on your computer.
Setting Up
[edit]The software used by Wikipedia, called MediaWiki, has an extension that provides a version of Lua that can be used within Wikipedia pages. The extension is called Scribunto.
For the purpose of this tutorial, the examples can be run in the Lua demo site. The print function is not available in Scribunto. See the example:
p = {}
p.loop = function(frame)
local out = {}
for idx = 1, 5 do
table.insert(out, idx)
end
return table.concat(out, "<br>")
end
return p
An equivalent of the code snippet above using the print function is:
for idx = 1, 5 do
print( idx )
end
A Lua module is used inside a wiki page by using a call like {{#invoke:yourModuleName|yourFunctionCall}}
.
Lua variable type
[edit]The variable name is the usual way to reference the stored value, in addition to referring to the variable itself, depending on the context. There are eight basic types of values in Lua: number, string, boolean, table, function, nil, userdata, thread. In Scribunto we make use of six out of the eight types available in the Lua programming language.
Numbers
[edit]The number type represents a floating-point (fractional) number. They represent real (double-precision floating-point) numbers.
Arithmetic operation with numbers
[edit]Lua allows simple arithmetic on numbers using the usual operators to add, subtract, multiply and divide.
print(2+2) -- Addition of numbers
4 -- Output
print(2-7) -- Subtraction operation
-5 -- Output
print(7*8) -- Multiplication operation
56 -- Output
print(7/8) -- Division operation
0.875 -- Output
From the example above, you observed that the numbers are not rounded into integers. They are floating point, or real numbers.
Assignment operator
[edit]In Lua, we can assign values to variables using the = operator.
x = 7 -- = operator assigns the number 7 to the variable x.
print(x) -- call a function to print out the value of x
7 -- output
From the example above, we can now use the value in x for other arithmetic operations.
x = x * 9
print(x)
63
print(x*2) -- will not change the value of x
126
print(x)
63 -- output: x has not been changed
String
[edit]Lua also uses string (i.e. text) types. To create strings, wrap text in "double quotes" or 'single quotes'. Strings in Lua can contain any 8-bit value, including embedded zeros, which can be specified as '\0'.
print("hello") -- quoted string
hello -- output
In Lua strings can be assigned to a variable just like we can for numbers:
name = "John"
print(name)
John -- output
Lua string concatenation is done using the .. operator and not the + operator, as shown below:
print("hello " .. name) -- the variable "name" has been assigned above
hello John -- output
Boolean
[edit]Boolean values have either the value true or false. The not operator can be placed before a boolean value to invert it.
x = true -- assign true to the variable
print(x) -- invoking the print function
true -- output
print(not x) -- using the not operator
false -- inverted output
print(not false)
true -- inverted output
Boolean values are used to represent the results of logic tests. The equals ==, and does not equal ~= operators will return boolean values depending on the values supplied to them
print(1 == 0) -- test whether two numbers are equal
false -- output
print(1 ~= 0) -- test whether two numbers are not equal
true -- output
print(true ~= false) -- is true not equal to false?
true
Note that for an assignment you use a single equals sign (=), but for comparison, you use a double equals sign (==), as shown in the examples above.
Tables
[edit]Lua has a general-purpose aggregate data type called a table. Aggregate data types are used for storing collections (such as lists, sets, arrays, and associative arrays) containing other objects (including numbers, strings, or even other aggregates).
Tables are created using a pair of curly brackets {}.
x = {} -- creating an empty table
print(x)
table: 0x237f670 -- output
It is normal if your table does not have the same unique identifier as in the above example.
Functions
[edit]In Lua, functions are assigned to variables, just like numbers and strings. Functions are created using the function keyword. It allows you to call the same code in multiple places. Let's create a simple function to print hello:
foo = function () print("hello") end -- declare the function
foo() -- call the function
hello -- Printed output
print(foo) -- get the value of the variable "foo"
function: 0035D6E8
You will notice that we could print the value of the variable foo (like tables). The value is a function with a unique identifier. From the example above, in Lua all values are treated the same way (first-class values).
nil
[edit]nil is a special value which indicates the lack of a useful value. If you try getting a variable that doesn't exist you will get nil:
print(x)
nil --output as x is undefined
x = 2.5 --x is assigned a value
print(x)
2.5 --value of x printed out
userdata
[edit]Userdata values are objects foreign to Lua, such as objects implemented in C. These typically come about when an object in a C library is exposed to Lua, so they aren't used in Scribunto.
thread
[edit]A thread value represents an independent (cooperative) thread of execution. This is not used in Scribunto.
Dynamic typing
[edit]Lua has dynamic typing. This means that types are checked while a program is running. Like many other programming languages with dynamic typing, in Lua you don't have to specify what type a variable is. The variable knows what type it is from the value, or object, assigned to it.
a = 1
b = "hello"
c = {}
In Lua we can also assign different types of values to the same variable, e.g.
a = 1
a = "hello"
a = {}
Querying type
[edit]You can use the Lua function type() to get a description of the type of a particular object.
x = "123" -- a string
print(x, type(x)) -- show the value of x and its type string
123 string -- output
x = x + 7 -- add a number to the string which forces coercion
print(x, type(x)) -- again show the value and type number
130 number -- output
Assignment statement
[edit]Setting the value of a variable is an assignment:
x = 1
y = "hello"
print(x,y)
1 hello
Multiple assignment
[edit]In Lua you can perform multiple assignments in a single statement, e.g.,
x, y = 2, "there" --multiple assignment
print(x,y)
2 there --output
a,b,c,d,e,f = 1,"two",3,3.14159,"foo",{ this="a table" }
print(a,b,c,d,e,f)
1 two 3 3.14159 foo table: 0035BED8
The list of values on the right is assigned to the list of variables on the left of the =. We can assign as many values as we like and they don't all have to be of the same type as seen in the example above.
However, multiple assignments come with a few limitations as described below:
Evaluation occurs before an assignment
[edit]Any expressions are evaluated first. The evaluated expression is then assigned.
i = 7
i, x = i+1, i
print(i, x)
8 7
When Lua reaches the second line it evaluates the expressions i+1 and i before anything else. After evaluation the second line becomes i, x = 8, 7. Then it performs the assignments.
Swapping values
[edit]You can use multiple assignments to swap variable values around:
a,b = 1,2 -- set initial values
print(a,b)
1 2 -- output
a,b = b,a -- swap values around
print(a,b)
2 1 -- output
a,b = b,a -- and back again
print(a,b)
1 2 -- output
Note that there is no need for a temporary variable (such as bold = b; b = a; a = bold;).
Assignment order
[edit]The order in which multiple assignments are performed is not defined. This means you shouldn't assume the assignments are made from left to right. If the same variable or table reference occurs twice in the assignment list the results may surprise you.
a, a = 1, 2
print(a)
1 -- output
In the above example, Lua does assignments from right-to-left, e.g. a=2 and then a=1. You should use separate assignment statements if the order of assignment is important to you.
Mismatched list sizes
[edit]If a value list is longer than the variable list the extra values are ignored.
a,b,c = 1,2,3,4,5,6
print(a,b,c)
1 2 3 -- output
Lua assigns the value nil to the variables without a value if a value list is shorter than the variable list.
a,b,c,d = 1,2
print(a,b,c,d)
1 2 nil nil -- output
Number manipulations
[edit]Lua supports only one type of number: floating-point number. By default, these are double-precision floating-point numbers. However, Lua could be recompiled to support single-precision floating-point numbers should you so desire.
Actually, Lua can also support numbers stored as integers, and this may change between implementations and versions.
The Lua 5.1 manual says that "Number represents real (double-precision floating-point) numbers. (It is easy to build Lua interpreters that use other internal representations for numbers, such as single-precision float or long integers; see the file luaconf.h.)"
The Lua 5.3 manual however says that "The type number uses two internal representations or two subtypes, one called integer and the other called float. Lua has explicit rules about when each representation is used, but it also converts between them automatically as needed (see §3.4.3). Therefore, the programmer may choose to mostly ignore the difference between integers and floats or to assume complete control over the representation of each number."
You'll find that pasting x=30/3 y=math.floor(x) print(x, y)
into https://www.lua.org/cgi-bin/demo and running it will give "10.0 10", but trying that with Scribunto in Wikipedia gives "10 10" instead. Our version of Lua now understands integers in a smart manner.
If you use numbers with fractional parts (or division), they may have a rounding error. Numbers which have infinitely repeating patterns in decimal will not have them in binary, so don't assume that any fractional number is safe.
You don't use the == operator with fractional numbers since it checks for perfect equality. Remember to write your code in such a way that rounding errors don't build up over time.
When your numbers are integers (with no fractional part), and they don't reach 2^53; then you won't need to worry about these issues.
Performing calculation in Lua
[edit]We can use the Lua interactive command-line prompt as a calculator by prefixing an expression by =. This can be performed also on the Lua demo.
= 1 + 2
3
Lua also understands exponent types for expressing numbers in the form <value>e<exponent> or <value>E<exponent>, which represents <value> * 10 ^ <exponent>.
= 543.21E8
54321000000
= 2.56e-4
0.000256
You can assign numbers to variables and do arithmetic:
width = 7.5
height = 12.7
= width * height
95.25
Number conversion
[edit]You can convert strings to numbers using the function tonumber(). This takes a string argument and returns a number.
= tonumber("123") + 25
148
x = tonumber("123.456e5")
print(x)
12345600
For converting integers to floating points, this calculation returns a decimal format of the converted integer:
= (16 ^ 13) + 10 - (16 ^ 13)
10.0
Coercion
[edit]Lua will automatically convert string and number types to the correct format to perform calculations. If you try to apply an arithmetic operation to a string Lua will try to convert that string to a number first. Otherwise, the operation will not work. This automatic conversion of types is called coercion.
= 100 + "7"
107 --output
= "hello" + 234
stdin:1: attempt to perform arithmetic on a string value
stack traceback:
stdin:1: in main chunk
[C]: ?
You can see the calculation succeeds where a string was converted to a number. The string "hello" cannot be converted to a number and so an error occurs. This works in Lua because it is dynamically typed.
A notable exception: comparison operators (== ~= < > <= >=) do not coerce their arguments. Ordered comparison operators throw an error when you feed them different types.
= 100 == "100"
false
= 100 ~= "hello"
true
= 100 == tonumber("100")
true
= 100 <= "100"
stdin:1: attempt to compare number with string
stack traceback:
stdin:1: in main chunk
[C]: ?
For performance reasons, you should avoid relying on automatic coercion too much. Make sure that all numbers in performance-sensitive computations (especially in inner loops) are of the proper type.
String
[edit]Strings can be defined using single quotes, double quotes, or double square brackets.
= "hello"
hello
= 'hello'
hello
= [[hello]]
hello
You can enclose one type of quotes in the other. e.g..
= 'hello "Lua user"'
hello "Lua user" -- output
= "Its [[content]] hasn't got a substring."
Its [[content]] hasn't got a substring. -- output
Double bracketed strings also have a few other special properties.
Escape sequences
[edit]Lua can also handle C-like escape sequences.
= "hello \"Lua user\""
hello "Lua user" -- output
= 'hello\nNew line\tTab'
hello
New line Tab
Escape sequences are not recognized when using double brackets, so:
= [[hello\nNew line\tTab]]
hello\nNew line\tTab
Multiline quotes
[edit]Double square brackets can be used to enclose literal strings which traverse several lines. e.g.,
= [[Multiple lines of text
>> can be enclosed in double square
>> brackets.]]
Multiple lines of text
can be enclosed in double square
brackets.
Nesting quotes
[edit]Double square brackets allow nesting, but they require one or more = inserted in the outer-most brackets to distinguish them. It doesn't matter how many = are inserted, as long as the number is the same in the beginning and ending brackets.
= [[one [[two]] one]] -- bad
stdin:1: nesting of [[...]] is deprecated near '[' -- returns an error
= [=[one [[two]] one]=] -- ok
one [[two]] one
= [===[one [[two]] one]===] -- ok too
one [[two]] one
Concatenation
[edit]Strings can be joined together using the concatenation operator "..". e.g.,
who = "John"
= "hello "..who
hello John -- output
Numbers can be concatenated to strings. In this case, they are coerced into strings and then concatenated. You can read more about coercion below
= "Green bottles: "..10 -- concatenating a string and integer
Green bottles: 10 -- output
= type("Green bottles: "..10) -- using the type function
string -- output
Doing a large number of concatenation operations may be slow because each concatenation may allocate a new string in memory.
Coercion in string
[edit]Lua performs automatic conversion of numbers to strings and vice versa where it is appropriate. This is called coercion.
= "This is Lua version " .. 5.1 .. " we are using."
This is Lua version 5.1 we are using.
= "Pi = " .. math.pi
Pi = 3.1415926535898
As shown above, during coercion, we do not have full control over the formatting of the conversion. To format the number as a string as we would like we can use the string.format() function. e.g.,
= string.format("%.3f", 5.1)
5.100
= "Lua version " .. string.format("%.1f", 5.1)
Lua version 5.1
This is an explicit conversion using a function to convert the number, rather than coercion.
String library
[edit]Lua supplies a range of useful functions for processing and manipulating strings in its standard library. Below are a few examples of usage of the string library.
= string.byte("ABCDE", 2) -- return the ASCII value of the second character
66
= string.char(65,66,67,68,69) -- return a string constructed from ASCII values
ABCDE
= string.find("hello Lua user", "Lua") -- find substring "Lua"
7 9
= string.find("hello Lua user", "l+") -- find one or more occurrences of "l"
3 4
= string.format("%.7f", math.pi) -- format a number
3.1415927
= string.format("%8s", "Lua") -- format a string
Lua
Lua expressions
[edit]Expressions are evaluated in order to perform calculations which may assign values to variables or pass arguments to functions.
We'll use the = expression shorthand notation for this page. The values can be assigned to a variable, e.g.,
x = 7
print(x)
7 -- output
= 7
7 -- output
Arithmetic expressions
[edit]Lua has the usual binary arithmetic operators.
= 2+3, 5-12, 2*7, 7/8
5 -7 14 0.875 --output
- Unary negation:
= -(-10), -(10)
10 -10
- Modulo (division remainder):
= 15%7, -4%3, 5.5%1
1 2 0.5
Control statement
[edit]Control structures let your program make choices, or run the same piece of code multiple times.
if statement
[edit]The if statement lets you run different code based on a condition:
if condition then
block
elseif condition2 then
block
elseif condition3 then
block
else
block
end
The if and elseif parts are checked in order, and once one of the conditions is true, it runs the block under it and skips to the end, ignoring any other elseif conditions after it. The else block is run if none of the conditions matches. Finally, the elseif and else parts are optional.
> n = 5
> if n > 5 then print("greater than 5") else print("less than 5") end
less than 5
> n = 7
> if n > 5 then print("greater than 5") else print("less than 5") end
greater than 5
For a more complex example:
> n = 12
> if n > 15 then
>> print("the number is > 15")
>> elseif n > 10 then
>> print("the number is > 10")
>> elseif n > 5 then
>> print("the number is > 5")
>> else
>> print("the number is <= 5")
>> end
the number is > 10
You noticed how just one of the messages is printed, even though more than one of the conditions are true. This is because once a condition matches, the if statement skips checking the other conditions.
while loop
[edit]while condition do
block
end
This runs the block over and over in a loop on each iteration. It checks the condition and if it's false, skips to the end and breaks the loop. If the condition is always false, the block will never run.
> i = 1
> while i <= 10 do
>> print(i)
>> i = i + 1
>> end
1
2
3
4
5
6
7
8
9
10
repeat loop
[edit]repeat
block
until condition
This is same as the while loop, except the condition is inverted (breaks the loop when true).
> i = 5
> repeat
>> print(i)
>> i = i - 1
>> until i == 0
5
4
3
2
1
The condition is checked after the first iteration, so the code is guaranteed to run at least once.
numeric for loop
[edit]for variable = start, stop, step do
block
end
Runs the block with a variable first being equal to start, then keeps incrementing it step amount and running the block again until it's greater than stop. step can be omitted and will default to 1.
You can also make the step negative, and the loop will stop once the counter variable is less than the stop value.
> for i = 1, 5 do
>> print(i)
>> end
1
2
3
4
5
> for i = 1, 100, 8 do
>> print(i)
>> end
1
9
17
25
33
41
49
57
65
73
81
89
97
> for i = 3, -3, -1 do
>> print(i)
>> end
3
2
1
0
-1
-2
-3
Also, remember that the variable in a for loop is only visible inside the block.
iterator for loop
[edit]for var1, var2, var3 in iterator do
block
end
The iterator version of the for loop takes a special iterator function and can have any amount of variables. What the loop does and how many variables it needs depends on the iterator. See the example below:
> tbl = {"a", "b", "c"}
> for key, value in ipairs(tbl) do
>> print(key, value)
>> end
1 a
2 b
3 c
The ipairs is the iterator, which gets the numbered entries from a table in order.
break statement
[edit]The break statement causes Lua to jump out of the current loop:
> i = 3
> while true do -- infinite loop
>> print(i)
>> i = i + 1
>> if i > 6 then
>>> break
>> end
> end
3
4
5
6
With nested loops, break only affects the innermost one:
> for i = 1, 2 do
>> while true do
>>> break
>> end
>> print(i)
> end
1
2
Using break outside of a loop is a syntax error:
> break
stdin:1: <break> at line 1 not inside a loop
Conditions
[edit]Conditions don't necessarily have to be boolean values. In fact, any value is a valid condition: nil and false make the condition false, anything else (including 0) makes it true.
> if 5 then print("true") else print("false") end
true
> if 0 then print("true") else print("false") end
true
> if true then print("true") else print("false") end
true
> if {} then print("true") else print("false") end
true
> if "string" then print("true") else print("false") end
true
> if nil then print("true") else print("false") end
false
> if false then print("true") else print("false") end
false
In Lua, assignment is a statement and not an expression. See the example below for a syntax error:
> i = 0
> while (i = i + 1) <= 10 do print(i) end
stdin:1: ')' expected near '='
if/else as an expression
[edit]Lua doesn't have a ternary operator that acts like an if/else statement, but in many cases, you can imitate it using the and and or logical operators. This works for two reasons:
- Those operators don't even run the right-side expression if the logical result is known only from the left side result
- They directly return the result of their sub-expressions, instead of converting them to boolean:
> = true and print("test")
test
nil
> = false and print("test") -- 'and' is always false if one of the sides are false, don't bother running the other expression
false
> = true or print("test") -- 'or' is always true if one of the sides are true, don't bother running the other expression
true
> = false or print("test")
test
nil
> = 8 or 5
8
> = true and "text"
text
This can be used to make a simple if/else expression:
> condition = true
> = condition and 2 or 4
2
> condition = false
> = condition and 2 or 4
4
> = condition and print("a") or print("b") -- only the "false" branch is run, otherwise both a and b would be printed
b
nil
Also remember that and has a higher precedence than or. If the condition is false, it makes the and expression give up and return false. This then makes the or part try its right-side expression and return its value. If the condition is true, and will return its right-side expression. This is then given to or, which sees that the left result is a true condition, and just returns it.
Note that we assumed that the result of the true branch is a value that acts as a true condition. This leads to the catch: the true branch cannot evaluate to nil or false because then the false branch will also be run and its value will be returned:
> condition = true
> = condition and false or true -- wrong result!
true
This is because the whole "and" sub-expression is now false, causing "or" to try running its other sub-expression. But it is alright to return a false value from the false branch. In fact, if you're in a situation like the above example, you can just invert the condition and swap the contents of the branches:
> condition = true
> = not condition and true or false
false
But if both branches must return a value that acts like a false condition, there's no way to work around that.
An if statement can be followed by an optional elseif...else statement, which is very useful to test various conditions using single if...elseif statement.
While using if, elseif, else statements, there are a few points to keep in mind
- An if can have zero or one else's and it must come after any elseif's.
- An if can have zero to many elseif's and they must come before the else.
- Once an elseif succeeds, none of the remaining elseif's or else's will be tested.
a = 100
if(a ==10)
then
print("Value of a is 10")
elseif(a == 20)
then
print("Value of a is 20")
elseif(a == 30)
then
print("Value of a is 30")
else
print("None of the values is matching")
end
print("Exact value of a is: ", a )
When you build and run the above code, it produces the following result.
None of the values is matching
The exact value of a is: 100
Lua tables
[edit]Tables are the only "container" type in Lua. They are associative arrays, which means they store a set of key/value pairs. In a Key/Value pair you can store a value under a key and then later retrieve the value using that key.
Creating tables
[edit]Tables are created using table constructors, which are defined using curly brackets, i.e. { }. To define an empty table we can do the following.
> t = {} -- construct an empty table and assign it to variable "t"
> print(t)
table: 0035AE18
Notice when the value of a table is displayed, only the type and unique id of the object are displayed. To print out the contents of a table we must do so explicitly.
Using tables
[edit]To access the value associated with the key in a table you can use the table[key] syntax:
> t = {}
> t["foo"] = 123 -- assign the value 123 to the key "foo" in the table
> t[3] = "bar" -- assign the value "bar" to the key 3 in the table
> = t["foo"]
123
> = t[3]
bar
if there's no value associated with the key, its not an error, instead the result will be nil:
> t = {}
> = t["foo"]
nil -- result is a nil not an error
You can erase a key/value pair from a table by assigning nil to the value.
> t["foo"] = nil
Any value can be used as a key (not just numbers and strings). Just make sure it's not nil or NaN (Not a Number):
> t = {}
> k = {}
> f = function () end
> t[k] = 123
> t[f] = 456
> = t[k]
123
> = t[f]
456
> t[nil] = 123
stdin:1: table index is nil
stack traceback:
stdin:1: in main chunk
[C]: in ?
> t[0/0] = 123
stdin:1: table index is NaN
stack traceback:
stdin:1: in main chunk
[C]: in ?
It's so common to use string constants as keys there's a special shortcut syntax for it:
> t = {}
> t.foo = 123 -- same as t["foo"] (but not t[foo], which would use the variable foo as the key)
> = t.foo
123
> = t["foo"]
123
The shortcut syntax is only valid if the string consists of underscores, letters, and numbers, but doesn't start with a number.
You can also add key/value associations right inside the {} syntax:
> t = {["foo"] = "bar", [123] = 456}
> = t.foo
bar
> = t[123]
456
There is also a syntax shortcut for string keys in {}, as long as the string conforms to the same rules as the . syntax:
> t = {foo = "bar"} -- same as ["foo"]="bar" (but not [foo]="bar" , that would use the variable foo)
> = t["foo"]
bar
> = t.foo
bar
To loop over all the key/value pairs in a table, use the pairs iterator:
> t = {foo = "bar", [123] = 456}
> for key,value in pairs(t) do print(key,value) end
foo bar
123 456
The order when looping with pairs is undefined. Just because you added one item after adding another doesn't mean that's the order they'll be in with pairs.
Inside a pairs loop, it's safe to reassign existing keys or remove them (by assigning nil to them), but not to add new keys (that had a nil value previously).
Tables as arrays
[edit]Tables are still just key/value containers because Lua doesn't actually have an array type. But tables can be treated like arrays, which are explained here:
Table constructors can contain a comma-separated list of objects to create an "array":
> t = {"a", "b", "c"}
> = t[1]
a
> = t[3]
c
This is a syntax shortcut for:
> t = {[1]="a", [2]="b", [3]="c"}
> = t[1]
a
> = t[3]
c
Note it's still just a key/value association.
You can also mix the array syntax with the usual key=value syntax:
> t = {"a", "b", [123]="foo", "c", name="bar", "d", "e"}
> for k,v in pairs(t) do print(k,v) end
1 a
2 b
3 c
4 d
5 e
123 foo
name bar
The first index is the number one, unlike most other languages that start with the number zero. The reason this was chosen is that it's often more intuitive. It was also chosen because it's just a key and not an offset from the beginning.
You can get the "length" of an array using the # operator:
> t = {"a", "b", "c"}
> = #t
3
The # operator doesn't count all the items in the table (!). Instead, it finds the last integer (non-fractional number) key. Because of how it's implemented its results are undefined if all the integer keys in the table aren't consecutive. Which is why it shouldn't be used for tables used as sparse arrays.
There are two ways to add an item to the end of an array:
> t = {}
> table.insert(t, 123)
> t[#t+1] = 456
> = t[1]
123
> = t[2]
456
table.insert takes an optional index parameter to insert into the middle of an array. It shifts up any other integer keys above the index:
> t = {"a", "c"}
> table.insert(t, 2, "b")
> = t[1], t[2], t[3]
a b c
table.remove removes an item from an array, shifting down any remaining integer keys:
> t = {"a", "b", "c"}
> table.remove(t, 2)
> = t[1], t[2]
a c
To loop over an array use ipairs. Unlike pairs it only gives you the consecutive integer keys from 1. It guarantees their order. With pairs the number keys will not necessarily be given in the correct order!
> t = {"a", "b", "c"}
> for i, v in ipairs(t) do print(i, v) end
1 a
2 b
3 c
To join together an array of strings there's table.concat. It takes an optional separator, starts, and end parameters. Here we only use the separator:
> t = {"a", "b", "c"}
> = table.concat(t, ";")
a;b;c
Table values are references
[edit]When you pass a table to a function or store it in a new variable, etc. a new copy of that table is not created. Tables do not act like numbers in these cases. Instead, the variable or function becomes a reference to the original table.
> t = {}
> u = t
> u.foo = "bar"
> = t.foo
bar
> function f(x) x[1] = 2 end
> f(t)
> = u[1]
2
Tables are freed from memory by the garbage collector after the last reference to them is gone. This does not always happen immediately, however. The garbage collector is designed to work correctly even if a table (directly or indirectly) contains a reference to itself.
Comparing tables using == will return false even if the two tables have the same contents. They must actually be references to the same table. Table comparison works by reference.
If you want to copy a table you'll have to do it manually. Lua offers no standard function for it mainly due to all the different ways you can copy a table.
Tables as unordered sets
[edit]People new to Lua will often create an array to store a group of objects even if the order isn't necessary. The problem with this is that removal is slow because the computer needs to shift down other items. Checking if an item is in the array is slow; again because the computer must loop over all the items.
This can be solved by storing items in the keys and setting values to a dummy value (like true). Doing that will help you use a table like an unordered set with fast insertion, removal, and lookup.
The main differences are that there's no easy way to get the count (you have to use a loop), and you can't store the same item twice in the set.
So if you need to store a group of items it's best to consider both sets and arrays to see what fits your situation best.
local items = {}
-- add some items to the set
items["foo"] = true
items[123] = true
-- is "foo" in the set?
if items["foo"] then
-- do stuff
end
-- remove item from the set
items[123] = nil
Introduction to functions
[edit]Functions let you store a piece of code in a value. They are useful to be able to run the same piece of code from multiple places, without having to duplicate it. Also, they let you change the behaviour of your program at runtime by giving different functions to different parts of your code.
Defining functions
[edit]Functions are created with the function keyword as follows:
function ( args ) body end
The following example shows a simple function that receives a single argument and returns twice its value:
> foo = function (n) return n*2 end
> = foo(7)
14
The arguments (also known as parameters) are specified inside the ( ) part, and values are returned from the function using the return keyword. Without the return, the function would return no values.
Functions are values
[edit]Notice that in the above example, we didn't actually "name" the function, we just assigned it to a variable. This is because in Lua, functions are regular values (like numbers, strings, tables, etc.), and you can do anything with them that you can do with any other value.
The function' block is an expression (in the same sense that "1 + 2" is an expression) that evaluates to a new function value. A function value can be called by using the ( ) operator, which runs the code in the function. The ( ) pair goes after the function expression, and optionally contains a comma-separated list of arguments.
This means that Lua functions are considered anonymous (no pre-set name), and first-class (not treated differently from other values).
Functions are passed by reference. if you assign a variable containing a function to another variable, you just create a new "handle" to the same function.
Function arguments
[edit]Functions can take 0 or more arguments. These are values given to the function when it's called, that the code stored in the function can use. Parameters look like a variable, but they only exist inside the function. See the example below:
> f = function (op, a, b)
>> if op == 'add' then
>> return a + b
>> elseif op == 'sub' then
>> return a - b
>> end
>> error("invalid operation")
>> end
> g = function (value)
>> print(value)
>> end
> = f('add', 1, 2) -- args are given inside (), separated by commas.
3
> = f('add', 1, 2, 123) -- extra args are ignored
3
> = f('add', 1) -- missing args aren't an error, instead they will be filled with nil, which might cause an error in the function's code
stdin:1: attempt to perform arithmetic on local 'b' (a nil value)
> = g() -- to call a function with no args, use ()
nil
> = g "example" -- the () can be omitted if you have one quoted string arg
example
> = g {} -- same with one table constructor
table: 0x820ee0
Function return values
[edit]Functions can also return values back to the code that called them using the return keyword. In Lua, a function can return any amount of values. To use this, put comma-separated values after the return keyword:
> f = function ()
>> return "x", "y", "z" -- return 3 values
>> end
> a, b, c, d = f() -- assign the 3 values to 4 variables. the 4th variable will be filled with nil
> = a, b, c, d
x y z nil
> a, b = (f()) -- wrapping a function call in () discards multiple return values
> = a, b
x, nil
> = "w"..f() -- using a function call as a sub-expression discards multiple returns
wx
> print(f(), "w") -- same when used as the arg for another function call...
x w
> print("w", f()) -- ...except when it's the last arg
w x y z
> print("w", (f())) -- wrapping in () also works here like it does with =
w x
> t = {f()} -- multiple returns can be stored in a table
> = t[1], t[2], t[3]
x y z
One thing to remember about the last example ( {f()} ) is that if the function returns nils, since nil in tables is considered "no value", , the # operator can't be reliably used to get the number of values because it's undefined if an array has "holes".
Lua functions actually return separate values, instead of a single container.
Return skips other code. See the example below:
function f(switch)
if not switch then --if switch is nil, function f() will not complete anything else below Return
return
end
print("Hello")
end
f()--doesn't print anything
f(1)--prints "hello", since switch is no longer nil but is instead "1"
Using functions as parameters and returns
[edit]Functions as parameters or using them as return values is a useful feature because it lets you plug in your own behaviour into existing code. One good example is table.sort, which can optionally take a custom "less than" function:
> list = {{3}, {5}, {2}, {-1}}
> table.sort(list)
attempt to compare two table values
stack traceback:
[C]: in function 'sort'
stdin:1: in main chunk
[C]: in?
> table.sort(list, function (a, b) return a[1] < b[1] end)
> for i,v in ipairs(list) do print(v[1]) end
-1
2
3
5
Variable number of arguments
[edit]A function can have ... at the end of its argument list. This will capture any remaining arguments (args) passed after the named ones. Then you can use ... inside the body of the function, and it will evaluate to the multiple values (with the same rules as functions called with multiple arguments).
For example, a function that passes its extra args unchanged to another function:
> f = function (x, ...)
>> x(...)
>> end
> f(print, "1 2 3")
1 2 3
To get a specific item from ..., use the select function, which takes a number and a variable number of args, and returns the args starting from that index. It can also take "#" as the index and return the amount of args:
> f=function(...) print(select("#", ...)) print(select(3, ...)) end
> f(1, 2, 3, 4, 5)
5
3 4 5
... can also be packed into a table:
> f=function(...) tbl={...} print(tbl[2]) end
> f("a", "b", "c")
b
A table with array items can also be "unpacked" to an arg list:
> f=function(...) tbl={...} print(table.unpack(tbl)) end -- in Lua 5.1 and older, use "unpack" instead of "table.unpack"
> f("a", "b", "c")
a b c
> f("a", nil, "c") -- undefined result, may or may not be what you expect
But in the second example, we see a problem: tables can't store nil, which means that the # operator (which table.unpack uses internally) can't be used, since it's undefined if the array has nil "holes". Even looping over the table to find the item with the biggest key won't get the real length if nil was the last arg to the function.
Named functions
[edit]Although Lua lets us use functions freely like any other value, we will usually just want to give them a name (by storing them in a variable) and use them by that name. Lua has some syntax sugar to make storing a function in a variable look nicer:
function f(...)
end
-- is equivalent to:
f = function (...)
end
Generally, it is recommended to use the shortcut syntax in real scripts unless there's no reason to give your function a name.
Also, there is a similar syntax for storing functions in tables:
function a.b.f(...)
end
-- is equivalent to:
a.b.f = function (...)
end
Lua scope
[edit]Until now you just assigned values to names and could get back the value by using the name anywhere in the script. This is fine for small examples, but now that you know functions, it can be a big problem: what if different functions use the same name to store temporary values? They will conflict and overwrite each other, making your script an impossible-to-debug mess. The solution is to control where your variables exist using the local keyword.
Creating local variables
[edit]To create local variables, add the local keyword before the assignment:
local a = 5
print(a)
You don't need the local keyword any more when changing the variable:
local a = 5
a = 6 -- changes the local a, doesn't create a global
Local variables only exist in the block they were created in. Outside of the block, they do not exist any more.
local a = 5
print(a) --> 5
do
local a = 6 -- create a new local inside the do block instead of changing the existing a
print(a) --> 6
end
print(a) --> 5
The place where a variable is visible is called the "scope" of a variable.
Now let's use functions to show how this is really useful:
function bar()
print(x) --> nil
local x = 6
print(x) --> 6
end
function foo()
local x = 5
print(x) --> 5
bar()
print(x) --> 5
end
foo()
As you can see, each variable is visible from the point where it's declared to the end of the block it's declared in. Even though bar's x exists at the same time as foo's x, they're not written in the same block, so they're independent. This is what's called lexical scoping.
Local function
[edit]local function f() end
-- is equivalent to
local f
f = function() end
-- not
local f = function() end
From the example above, if the contents of the function used f to get a reference to itself, it will correctly get the local variable in the first and second versions, but the third version will get the global f (which will be nil, if not a completely unrelated value set by some other code).
Closures
[edit]Functions can use local variables created outside of them. These are called upvalues. A function that uses upvalues is called a closure:
local x = 5
local function f() -- we use the "local function" syntax here, but that's just for good practice, the example will work without it
print(x)
end
f() --> 5
x = 6
f() --> 6
The function sees the change even if it's changed outside of the function. This means that the variable in the function is not a copy, it's shared with the outer scope.
Also, even if the outer scope has passed, the function will still hold on to the variable. If there were two functions created in the scope, they will still share the variable after the outer scope is gone.
local function f()
local v = 0
local function get()
return v
end
local function set(new_v)
v = new_v
end
return {get=get, set=set}
end
local t, u = f(), f()
print(t.get()) --> 0
print(u.get()) --> 0
t.set(5)
u.set(6)
print(t.get()) --> 5
print(u.get()) --> 6
Since the two values returned by the two calls to f are independent, we can see that every time a function is called, it creates a new scope with new variables.
Similarly, loops create a new scope on each iteration:
local t = {}
for i = 1, 10 do
t[i] = function() print(i) end
end
t[1]() --> 1
t[8]() --> 8
Usage
[edit]- Why are local variables difficult in the interactive interpreter
This is because it runs each line in a new scope:
> local a=5; print(a)
5
> print(a) -- a is out of scope now, so global a is used
nil
One thing you can do is wrap the code in a do-end block, but it won't be interactive until you finish writing the whole block:
> do
>> local a = 5
>> print(a) -- works on a new line
>> end
5
- Why not local by default?
x = 3
-- more code, you might have even forgotten about variable x by now...
function ()
-- ...
x = 5 -- does this create a new local x, or does it change the outer one?
-- ...
end
-- some more code...
The problem with changing the outer one is that you might have intended to make a new variable, and instead change the existing one that you might not even know about, introducing bugs.
The problem with creating a new one is what if you actually want to change the outer one?
With the local keyword, it's all explicit: without local, you change the existing variable, with it, you create a new one.
- When to use local variables
The general rule is to always use local variables unless it's necessary for every part of your program to be able to access the variable (which is very rare).
Since it's easy to forget a local, and since Lua doesn't warn you about it (instead silently creating a global), it can be a source of bugs. One solution is to use a script like strict.lua (shown below), that uses metatables to trap global variable creation and raise an error. You can put the script in a file in your project (for example at /w/extensions/Scribunto/includes/Engines/LuaCommon/lualib/strict.lua, which should become default in newer Mediawiki installations[1]), and do require("strict")
to use it.
-- strict.lua (fork of http://www.lua.org/extras/5.1/strict.lua)
-- checks uses of undeclared global variables
-- All global variables must be 'declared' through a regular assignment
-- (even assigning nil will do) in a main chunk before being used
-- anywhere or assigned to inside a function.
-- distributed under the Lua license: http://www.lua.org/license.html
-- Scribunto modifications:
-- * exempt arg, used by require()
-- * remove what(), since debug.getinfo isn't allowed
local error, rawset, rawget = error, rawset, rawget
local mt = getmetatable(_G)
if mt == nil then
mt = {}
setmetatable(_G, mt)
end
mt.__newindex = function (t, n, v)
if n ~= "arg" then
error("assign to undeclared variable '"..n.."'", 2)
end
rawset(t, n, v)
end
mt.__index = function (t, n)
if n ~= "arg" then
error("variable '"..n.."' is not declared", 2)
end
return rawget(t, n)
end
Lua metamethods
[edit]Lua has a powerful extension mechanism which allows you to overload certain operations on Lua objects. Each overloaded object has a metatable of function metamethods associated with it.
A metatable is a regular Lua table containing a set of metamethods, which are associated with events in Lua. Events occur when Lua executes certain operations, like addition, string concatenation, comparisons etc. Metamethods are regular Lua functions which are called when a specific event occurs. The events have names like "add" and "concat" which correspond with string keys in the metatable like "__add" and "__concat".
Metatables
[edit]We use the function setmetatable() to make a table act as a metatable for a certain object.
local x = {value = 5} -- creating local table x containing one key,value of value,5
local mt = {
__add = function (lhs, rhs) -- "add" event handler
return { value = lhs.value + rhs.value }
end
}
setmetatable(x, mt) -- use "mt" as the metatable for "x"
local y = x + x
print(y.value) --> 10 -- Note: print(y) will just give us the table code i.e table: <some tablecode>
local z = y + y -- error, y doesn't have our metatable. this can be fixed by setting the metatable of the new object inside the metamethod
When the addition operator finds that its operands aren't numbers, it tries checking if one of them has a metatable with an __add key. In this case it does, so it runs the function stored under that key in the metatable, equivalent to this:
local y = (getmetatable(x).__add(x, x)) -- x + x
Metatables are still triggered with math operators if one of the operands is a number. And the left operand is always the first parameter to the function, and the right operand is always the second. This means that the table that has the metamethod might not necessarily be the first parameter to the metamethod.
Metamethod types
[edit]Below are some metamethod events that lua handles.
__index
[edit]This is a very commonly used and versatile metamethod, you run a custom function or use a "fallback" table if a key in a table doesn't exist. If a function is used, its first parameter will be the table that the lookup failed on, and the second parameter will be the key. If a fallback table is used, remember that it can trigger an __index metamethod on it if it has one, so you can create long chains of fallback tables.
local func_example = setmetatable({}, {__index = function (t, k) -- {} an empty table, and after the comma, a custom function failsafe
return "key doesn't exist"
end})
local fallback_tbl = setmetatable({ -- some keys and values present, together with a fallback failsafe
foo = "bar",
[123] = 456,
}, {__index=func_example})
local fallback_example = setmetatable({}, {__index=fallback_tbl}) -- {} again an empty table, but this time with a fallback failsafe
print(func_example[1]) --> key doesn't exist
print(fallback_example.foo) --> bar
print(fallback_example[123]) --> 456
print(fallback_example[456]) --> key doesn't exist
__newindex
[edit]This metamethod is called when you try to assign to a key in a table, and that key doesn't exist (contains nil). If the key exists, the metamethod is not triggered.
local t = {}
local m = setmetatable({}, {__newindex = function (table, key, value)
t[key] = value
end})
m[123] = 456
print(m[123]) --> nil
print(t[123]) --> 456
Comparison operators
[edit]__eq is called when the == operator is used on two tables, the reference equality check failed, and both tables have the same __eq metamethod (!).
__lt is called to check if one object is "less than" another. Unlike __eq, it's not an error if the two objects have different __lt metamethods, the one on the left will be used.
That's all you need for all of the comparison operators to work with your object. But there will be some cases where both __lt and __eq will need to be called by the same operator. To avoid this, you can optionally add the __le (less than or equal to) metamethod. Now only one of the metamethods will be called with any of the comparison operators.
local mt
mt = {
__add = function (lhs, rhs)
return setmetatable({value = lhs.value + rhs.value}, mt)
end,
__eq = function (lhs, rhs)
return lhs.value == rhs.value
end,
__lt = function (lhs, rhs)
return lhs.value < rhs.value
end,
__le = function (lhs, rhs) -- not really necessary, just improves "<=" and ">" performance
return lhs.value <= rhs.value
end,
}
__metatable
[edit]__metatable is for protecting metatables. If you do not want a program to change the contents of a metatable, you set its __metatable field. With that, the program cannot access the metatable (and therefore cannot change it). see this for a list of all metamethods Metatable and metamethods
Lua environments
[edit]Unlike local variables, which are stored in a special data structure in the interpreter, global variables are just stored in a table. Each function has an environment table associated with it, that can be manipulated with the getfenv/setfenv standard functions.
getfenv and setfenv both take a function or stack level (where 1 is the current function, 2 is the function that called the current function, etc.). setfenv has a second parameter that takes the new env table, and getfenv returns the functions's current env table.
print(getfenv(1) == _G) -- prints true, since the default env is set to the global table
a = 1
local function f(t)
local print = print -- since we will change the environment, standard functions will not be visible
setfenv(1, t) -- change the environment
print(getmetatable) -- prints nil, since global variables (including the standard functions) are not in the new env
a = 2 -- create a new entry in t, doesn't touch the original "a" global
b = 3 -- create a new entry in t
end
local t = {}
f(t)
print(a, b) --> 1 nil
print(t.a, t.b) --> 2 3
Lua modules
[edit]Creating and using modules
[edit]Lua 5.0 and 5.1 have a module function that's used like this:
mymodule.lua:
module("mymodule", package.seeall)
function foo() -- create it as if it's a global function
print("Hello World!")
end
And it would be used like this:
> require "mymodule"
> mymodule.foo()
Hello World!
The way it works is it creates a new table for the module, stores it in the global named by the first argument to module, and sets it as the environment for the chunk, so if you create a global variable, it gets stored in the module table.
Lua standard libraries
[edit]Core functions
[edit]These functions provide access to the core functionality of Lua.
Assert(test, [message])
[edit]assert is similar to the assert() function in C. If the test condition is false or nil an error is raised; otherwise test is returned. An optional user-defined message is included in the error raised. Also, see the error() function. E.g.,
> assert(1==1) -- no error as test was true
> assert(1==0)
stdin:1: assertion failed!
stack traceback:
[C]: in function `assert'
stdin:1: in main chunk
[C]: ?
> assert("green"=="blue", "Colours not equal")
stdin:1: Colours not equal
stack traceback:
[C]: in function `assert'
stdin:1: in main chunk
[C]: ?
Many Lua functions, such as io.open, return a value on success, or return nil and an error message on failure. This works well with assert:
file = assert(io.open(filename))
This either opens filename for reading and assigns it to file, or it raises an error with the message in the second return value from io.open.
dofile(filename)
[edit]It opens the file and executes the contents of the file as a chunk. If no parameter is passed, then this function executes the contents of standard input. The errors will be propagated to the caller.
error (message[,level])
[edit]Errors may be "thrown" using the error() and assert() functions. To "catch" errors, use pcall() or xpcall(). Note that certain internal Scribunto errors cannot be caught in Lua code.
_G
[edit]_G is a global variable which points to the global environment. For example to display all of the globals variables we might do the following:
> table.foreach(_G,print)
string table: 00357098
xpcall function: 00354E10
tostring function: 00354708
gcinfo function: 00354E90
loadlib function: 00358B40
os table: 00355AE0
unpack function: 003547C8
level 2
require function: 00354F90
getfenv function: 00354548
... -- etc.
Lua itself does not use this variable, so changing its value does not affect any environment. You should use setfenv() to change environments.
getfenv(f)
[edit]Returns the current environment in use by the function. f can be a Lua function or a number that specifies the function at that stack level: Level 1 is the function calling getfenv. If the given function is not a Lua function, or if f is 0, getfenv returns the global environment. The default for f is 1.
getmetatable(object)
[edit]If the object does not have a metatable, returns nil. Otherwise, if the object's metatable has a "__metatable" field, returns the associated value. Otherwise, returns the metatable of the given object.
ipairs(t)
[edit]This functions fetches the indices and values of tables.
load(func [, chunkname])
[edit]Loads a chunk using function func to get its pieces. Each call to func must return a string that concatenates with previous results.
loadfile(filename)
[edit]Similar to load, but gets the chunk from file filename or from the standard input, if no file name is given.
loadstring(string [, chunkname])
[edit]Similar to load, but gets the chunk from the given string.
next(table [, index])
[edit]Allows a program to traverse all fields of a table. Its first argument is a table and its second argument is an index in this table. next returns the next index of the table and its associated value.
pairs(t)
[edit]Suspends the running coroutine. The parameter passed to this method acts as additional return values to the resume function.
print(e1, e2, ...)
[edit]print can be passed any number of comma-separated arguments which it prints the values of to stdout. print uses tostring to convert the arguments into string form to be printed. E.g.
> print(1,2,"buckle my shoe", 22/7)
1 2 buckle my shoe 3.1428571428571
print is very simple and will not recurse into tables printing the content, it will just print the type and a unique id.
> print({1,2,3})
table: 002FE9C8
print does not format text. In order to do this, you should use the string.format() function in conjunction with print(). E.g
> print(string.format("Pi is approximately %.4f", 22/7))
Pi is approximately 3.1429
tostring(e)
[edit]tostring converts its argument (just its first argument if there is more than one) to a string and returns that string. print is implemented using tostring so you are probably already familiar with the output format. Simple values (numbers, strings, booleans, and nil) are converted as you probably expect. Tables, Userdata, and Threads, are printed as `table:', `userdata:', or `thread:', followed by the address of an internal interpreter object (which should on no account be relied upon).
Note that unlike print, tostring doesn't print anything, it just converts its argument to a string and returns it.
tostring's behaviour is extensible. If the value to be converted has a metatable with a __tostring entry then that entry is called with the value to be converted and the result of that call is returned. This allows you to change how tostring works on (certain) tables, by giving them a metatable with a __tostring function that performs the conversion that you want.
type(v)
[edit]type returns a string describing the type of the object passed to it.
> = type(1), type(true), type("hello"), type({}), type(function() end)
number boolean string table function
Note, the type of nil is "nil".
> =type(nil)
nil
unpack(list)
[edit]unpack takes the elements of a list and returns them, e.g.:
> = unpack( {1,2,3} )
1 2 3
> = unpack( {"one",2,6*7} )
one 2 42
The number of elements unpacked is defined by the size of the table, which is not necessarily the number of elements in the table
> t = {"one",2,6*7}
> t.n = 2
> = table.getn(t)
2
> = unpack(t)
one 2
__Version
[edit]_VERSION is "a global variable (not a function) that holds a string containing the current interpreter version."
> = _VERSION
Lua 5.1
xpcall(f,err)
[edit]Certain internal errors cannot be intercepted.
rawget(table, index)
[edit]Gets the real value of table[index], without invoking any metamethod. the table must be a table; index may be any value.
rawequal(v1, v2)
[edit]Checks whether v1 is equal to v2, without invoking any metamethod. Returns a boolean.
rawset(table, index, value)
[edit]Sets the real value of table[index] to value, without invoking any metamethod. the table must be a table, index any value different from nil, and value any Lua value. This function returns the table.
require(packagename)
[edit]Can fetch certain built-in modules distributed with Scribunto, as well as modules present in the Module namespace of the wiki. To fetch wiki modules, use the full page name including the namespace. Cannot otherwise access the local filesystem.
setfenv(f, table)
[edit]Sets the environment to be used by the given function. f can be a Lua function or a number that specifies the function at that stack level − Level 1 is the function calling setfenv. setfenv returns the given function. As a special case, when f is 0 setfenv changes the environment of the running thread. In this case, setfenv returns no values.
select(index, ...)
[edit]If index is a number, returns all arguments after argument number index. Otherwise, index must be the string "#", and select returns the total number of extra arguments it received.
tonumber(e [, base])
[edit]Tries to convert its argument to a number. If the argument is already a number or a string convertible to a number, then tonumber returns this number; otherwise, it returns nil.
MathLibrary
[edit]Below is a summary of the functions and variables provided.
math.abs
[edit]Return the absolute, or non-negative value, of a given value.
> = math.abs(-100)
100
> = math.abs(25.67)
25.67
> = math.abs(0)
0
math.acos
[edit]Return the inverse cosine in radians of the given value.
> = math.acos(1)
0
> = math.acos(0)
1.5707963267949
math.asin
[edit]Return the inverse sine in radians of the given value.
> = math.asin(0)
0
> = math.asin(1)
1.5707963267949
math.atan
[edit]Return the inverse tangent in radians. You can do this by supplying y/x yourselves or we can pass y and x to math.atan to do this for us.
> c, s = math.cos(0.8), math.sin(0.8)
> = math.atan(s/c)
0.8
> = math.atan(s,c)
0.8
Using two arguments should usually be preferred, particularly when converting rectangular co-ordinates to polar co-ordinates. It will use the sign of both arguments to place the result into the correct quadrant, and also produces correct values when one of its arguments is 0 or very close to 0.
> = math.atan(1, 0), math.atan(-1, 0), math.atan(0, 1), math.atan(0, -1)
1.5707963267949 -1.5707963267949 0 3.1415926535898
math.ceil
[edit]Return the integer no less than the given value (even for negatives).
> = math.ceil(0.5)
1
> = math.ceil(-0.5)
-0
math.cos
[edit]Returns the cosine value for a given value in radians.
> = math.cos(math.pi / 4)
0.70710678118655
math.deg
[edit]Convert from degrees to radians
> = math.deg(math.pi)
180
> = math.deg(math.pi / 2)
90
math.exp
[edit]math.exp(myval) returns e (the base of natural logarithms) raised to the power myval.
> = math.exp(0)
1
> = math.exp(1)
2.718281828459
> = math.exp(27)
532048240601.8
math.floor
[edit]Return the integer no greater than than the given value (even for negatives).
> = math.floor(0.5)
0
> = math.floor(-0.5)
-1
math.huge
[edit]math.huge is a constant. It represents +infinity.
> = math.huge
inf
> = math.huge / 2
inf
> = -math.huge
-inf
> = math.huge/math.huge -- indeterminate
nan
> = math.huge * 0 -- indeterminate
nan
> = 1/0
inf
> = (math.huge == math.huge)
true
> = (1/0 == math.huge)
true
Note that some operations on math.huge return a special "not-a-number" value that displays as nan. This is a bit of a misnomer. nan is a number type, though it's different from other numbers:
> = type(math.huge * 0)
number
math.log
[edit]math.log() returns the inverse of this. math.exp(1) returns e.
> = math.log(532048240601)
26.999999999998
> = math.log(3)
1.0986122886681
math.max
[edit]Return the maximum value from a variable length list of arguments.
> = math.max(1.2, -7, 3)
3
> = math.max(1.2, 7, 3)
7
math.min
[edit]Return the minimum value from a variable length list of arguments.
> = math.min(1,2)
1
> = math.min(1.2, 7, 3)
1.2
> = math.min(1.2, -7, 3)
-7
math.modf
[edit]Return the integral and fractional parts of the given number.
> = math.modf(5)
5 0
> = math.modf(5.3)
5 0.3
> = math.modf(-5.3)
-5 -0.3
If you want the modulus (remainder), look for the modulo % operator instead.
math.pi
[edit]This is a part of the constant Pi.
> = math.pi
3.1415926535898
math.random
[edit]math.random() generates pseudo-random numbers uniformly distributed. Supplying argument alters its behaviour:
- math.random() with no arguments generates a real number between 0 and 1.
- math.random(upper) generates integer numbers between 1 and upper (both inclusive).
- math.random(lower, upper) generates integer numbers between lower and upper (both inclusive).
> = math.random()
0.0012512588885159
> = math.random()
0.56358531449324
> = math.random(100)
20
> = math.random(100)
81
> = math.random(70,80)
76
> = math.random(70,80)
75
upper and lower must be integer. In other case Lua casts upper into an integer, sometimes giving math.floor(upper) and others math.ceil(upper), with unexpected results (the same for lower).
math.randomseed
[edit]The math.randomseed() function sets a seed for the pseudo-random generator: Equal seeds produce equal sequences of numbers.
> math.randomseed(1234)
> = math.random(), math.random(), math.random()
0.12414929654836 0.0065004425183874 0.3894466994232
> math.randomseed(1234)
> = math.random(), math.random(), math.random()
0.12414929654836 0.0065004425183874 0.3894466994232
A good* 'seed' is os.time(), but wait a second before calling the function to obtain another sequence! To get nice random numbers use:
math.randomseed( os.time() )
math.sin
[edit]Returns the sine value for a given value in radians.
> = math.sin(0.123)
0.12269009002432
math.tan
[edit]Returms the tangent value for a given value in radians.
> = math.tan(5/4)
3.0095696738628
> = math.tan(.77)
0.96966832796149
StringLibrary
[edit]In Lua string indices start at index value 1 (as they do in BASIC), not at index value 0 (as they do in C), and they can be negative. Negative indices are counted from the end of string. For instance, index -2 in "miner" is "e", thus, -1 is #s (s is the string).
string.byte(s [, i[, j]])
[edit]- s:byte([i [, j]])
Return the numerical code(You can search the list of numerical codes ) of s[i] to s[j] of the string passed.
> = string.byte("ABCDE") -- no index, so the First character
65
> = string.byte(" ") --Whitespace also has its own numerical code
32
> = string.byte("H A I") -- Thus, #s of this string is 5 not 3
> = string.byte("ABCDE",1) -- indexes start at 1
65
> = string.byte("ABCDE",0) -- we're not using C
> = string.byte("ABCDE",100) -- index out of range, no value returned
> = string.byte("ABCDE",3,4)
67 68
> s = "ABCDE"
> = s:byte(3,4) -- can apply directly to string variable
67 68
string.char(i1, i2, ...)
[edit]Generate a string representing the character codes passed as arguments. Numerical codes are not necessarily portable across platforms.
> = string.char(65,66,67)
ABC
> = string.char() -- empty string
string.dump(function)
[edit]Returns a binary representation of the given function, so that a later load string on that string returns a copy of the function. The function must be a Lua function without upvalues.
string.find(s, pattern [, index [, plain]])
[edit]Find the first occurrence of the pattern in the string passed. If an instance of the pattern is found a pair of values representing the start and end of the string is returned. If the pattern cannot be found nil is returned.
> = string.find("Hello Lua user", "Lua")
7 9
> = string.find("Hello Lua user", "banana")
nil
We can optionally specify where to start the search with a third argument. The argument may also be negative which means we count back from the end of the string and start the search.
> = string.find("Hello Lua user", "Lua", 1) -- start at first character
7 9
> = string.find("Hello Lua user", "Lua", 8) -- "Lua" not found again after character 8
nil
> = string.find("Hello Lua user", "e", -5) -- first "e" 5 characters from the end
13 13
string.format(s, e1, e2, ...)
[edit]Create a formatted string from the format and arguments provided. This is similar to the printf("format",...) function in C. An additional option %q puts quotes around a string argument's value.
- A, a, c, d, E, e, f, G, g, i, o, u, X, and x all expect a number as an argument.
- q and s expect a string.
> = string.format("%s %q", "Hello", "Lua user!") -- string and quoted string
Hello "Lua user!"
> = string.format("%c%c%c", 76, 117, 97) -- char
Lua
> = string.format("%e, %E", math.pi, math.pi) -- exponent
3.141593e+000, 3.141593E+000
> = string.format("%f", math.pi) -- float
3.141593
> = string.format("%g, %g", math.pi, 10^9) -- float or exponent
3.14159, 1e+09
> = string.format("%d, %i, %u", -100, -100, -100) -- signed, signed, unsigned integer
-100, -100, 4294967196
> = string.format("%o, %x, %X", -100, -100, -100) -- octal, hexadecimal, hexadecimal
37777777634, ffffff9c, FFFFFF9C
> = string.format("%a, %A", 127, 127) -- hexadecimal with binary exponent (lowercase, uppercase)
0x1.fcp+6, 0X1.FCP+6
string.gmatch(s, pattern)
[edit]This returns a pattern finding iterator. The iterator will search through the string passed looking for instances of the pattern you passed.
> for word in string.gmatch("Hello Lua user", "%a+") do print(word) end
Hello
Lua
user
string.gsub(s, pattern, replace [, n])
[edit]This is a very powerful function and can be used in multiple ways. Used simply it can replace all instances of the pattern provided with the replacement. A pair of values is returned, the modified string and the number of substitutions made. The optional fourth argument n can be used to limit the number of substitutions made:
> = string.gsub("Hello banana", "banana", "Lua user")
Hello Lua user 1
> = string.gsub("banana", "a", "A", 2) -- limit substitutions made to 2
bAnAna 2
Just like string.find() we can use patterns to search in strings. If a capture is used this can be referenced in the replacement string using the notation %capture_index
> = string.gsub("banana", "(an)", "%1-") -- capture any occurences of "an" and replace
ban-an-a 2
> = string.gsub("banana", "a(n)", "a(%1)") -- brackets around n's which follow a's
ba(n)a(n)a 2
> = string.gsub("banana", "(a)(n)", "%2%1") -- reverse any "an"s
bnanaa 2
If the replacement is a function, not a string, the arguments passed to the function are any captures that are made. If the function returns a string, the value returned is substituted back into the string.
> = string.gsub("Hello Lua user", "(%w+)", print) -- print any words found
Hello
Lua
user
3
> = string.gsub("Hello Lua user", "(%w+)", function(w) return string.len(w) end) -- replace with lengths
5 3 4 3
> = string.gsub("banana", "(a)", string.upper) -- make all "a"s found uppercase
bAnAnA 3
> = string.gsub("banana", "(a)(n)", function(a,b) return b..a end) -- reverse any "an"s
bnanaa 2
string.len(s)
[edit]Return the length of the string passed.
> = string.len("Lua")
3
> = string.len("")
0
> = string.len("Lua\000user") -- Lua strings are 8 bytes pure so \000 does not terminate
8
string.lower(s)
[edit]Make uppercase characters lower case.
> = string.lower("Hello, Lua user!")
hello, lua user!
string.match (s, pattern [, index])
[edit]Extract substrings by matching patterns.
> = string.match("I have 2 questions for you.", "%d+ %a+")
2 questions
> = string.format("%d, %q", string.match("I have 2 questions for you.", "(%d+) (%a+)"))
2, "questions"
string.rep(s, n)
[edit]Generate a string which is n copies of the string passed concatenated together.
> = string.rep("Lua ",5)
Lua Lua Lua Lua Lua
> = string.rep("Lua\n",3)
Lua
Lua
Lua
string.reverse(s)
[edit]Reverses a string.
> = string.reverse("lua")
aul
string.sub(s, i [, j])
[edit]Return a substring of the string passed. The substring starts at i. If the third argument j is not given, the substring will end at the end of the string. If the third argument is given, the substring ends at and includes j.
> = string.sub("Hello Lua user", 7) -- from character 7 including 7 until the end
Lua user
> = string.sub("Hello Lua user", 7, 9) -- from character 7 until and including 9
Lua
> = string.sub("Hello Lua user", -8) -- 8 from the end until the end
Lua user
> = string.sub("Hello Lua user", -8, 9) -- 8 from the end until 9 from the start
Lua
> = string.sub("Hello Lua user", -8, -6) -- 8 from the end until 6 from the end
Lua
string.upper(s)
[edit]Make all the lower case characters upper case.
> = string.upper("Hello, Lua user!")
HELLO, LUA USER!
TableLibrary
[edit]Most functions in the table library assume that the table represents an array or a list. For these functions, when we talk about the "length" of a table we mean the result of the length operator [i.e. #].
table.concat(table [, sep [, i [, j]]])
[edit]Concatenate the elements of a table to form a string. Each element must be able to be coerced into a string. A separator can be specified which is placed between concatenated elements. Additionally, a range can be specified within the table, starting at the ith element and finishing at the j-th element.
> = table.concat({ 1, 2, "three", 4, "five" })
12three4five
> = table.concat({ 1, 2, "three", 4, "five" }, ", ")
1, 2, three, 4, five
> = table.concat({ 1, 2, "three", 4, "five" }, ", ", 2)
2, three, 4, five
> = table.concat({ 1, 2, "three", 4, "five" }, ", ", 2, 4)
2, three, 4
concat will fail on a table that contains tables because they cannot be coerced into strings.
> = table.concat({ 1,2,{} })
stdin:1: bad argument #1 to `concat' (table contains non-strings)
stack traceback:
[C]: in function `concat'
stdin:1: in main chunk
[C]: ?
table.sort(table [, comp])
[edit]Sort the elements of a table in-place (i.e. alter the table).
> t = { 3,2,5,1,4 }
> table.sort(t)
> = table.concat(t, ", ") -- display sorted values
1, 2, 3, 4, 5
If the table has a specified size only the range specified is sorted, e.g.,
> t = { 3,2,5,1,4; n=3 } -- construct a table with user size of 3
> table.sort(t) -- sort will be limited by user size
> = table.concat(t, ", ") -- only specified size is concatenated as well
2, 3, 5
A comparison function can be provided to customise the element sorting. The comparison function must return a boolean value specifying whether the first argument should be before the second argument in the sequence. The default behaviour is for the < comparison to being made. For example, the following behaves the same as no function being supplied:
> t = { 3,2,5,1,4 }
> table.sort(t, function(a,b) return a<b end)
> = table.concat(t, ", ")
1, 2, 3, 4, 5
You can see if we reverse the comparison the sequence order is reversed.
> table.sort(t, function(a,b) return a>b end)
> = table.concat(t, ", ")
5, 4, 3, 2, 1
table.insert(table, [pos,] value)
[edit]Insert a given value into a table. If a position is given insert the value before the element currently at that position:
> t = { 1,3,"four" }
> table.insert(t, 2, "two") -- insert "two" at position before element 2
> = table.concat(t, ", ")
1, two, 3, four
If no position is specified we append the value to the end of the table:
> table.insert(t, 5) -- no position given so append to end
> = table.concat(t, ", ")
1, two, 3, four, 5
When a table has an element inserted both the size of the table and the element indices are updated:
> t = { 1,"two",3 } -- create a table
> = # t -- find current size
3
> table.foreach(t, print) -- display the table contents
1 1
2 two
3 3
> table.insert(t, 1, "inserted") -- insert an element at the start
> = table.concat(t, ", ") -- see what we have
inserted, 1, two, 3
> = # t -- find the size
4
> table.foreach(t, print) -- the indexes have been updated
1 inserted
2 1
3 two
4 3
When no position is specified the element is inserted at the end of the table according to the calculated size. The size of a table may be user-specified and not reflect the number of elements, e.g.,
> t = { 1,"two",3; n=10 } -- create a table with user size
> table.insert(t, "end") -- insert with no position inserts at "end"
> table.foreach(t, print) -- display the table contents
1 1
2 two
3 3
11 end
n 11
table.remove(table [, pos])
[edit]Remove an element from a table. If a position is specified the element at that the position is removed. The remaining elements are reindexed sequentially and the size of the table is updated to reflect the change. The element removed is returned by this function. E.g.,
> t = { 1,"two",3,"four" } -- create a table
> = # t -- find the size
4
> table.foreach(t, print) -- have a look at the elements
1 1
2 two
3 3
4 four
> = table.remove(t,2) -- remove element number 2 and display it
two
> table.foreach(t, print) -- display the updated table contents
1 1
2 3
3 four
> = # t -- find the size
3
If no position is given remove the last element in the table which is specified by the size of the table. E.g.,
> t = { 1,"two","three" }
> = # t -- find the table size (which is removed)
3
> table.foreach(t, print) -- display contents
1 1
2 two
3 three
> = table.remove(t) -- remove the element at position "n"
three
> table.foreach(t, print) -- display updated contents
1 1
2 two
> = # t -- display new size
2
If the size of the table does not reflect the number of elements nothing is removed, e.g.,
> t = {1,2,3}
> table.setn(t,10) -- set user size
> table.foreach(t, print) -- display table contents, note size "n" is stored internally
1 1
2 2
3 3
> = # t -- find the size
10
> = table.remove(t) -- remove last element
nil
> = # t -- find the updated size
9
> table.foreach(t, print) -- display elements
1 1
2 2
3 3
Note that table.remove only works with numeric indexes. For dictionaries you can just unset tables entries with tablevariable["index"] = nil;
OsLibrary
[edit]You can find details about the operating system library.
os.clock()
[edit]Return CPU time since Lua started in seconds.
> = os.clock()
11056.989
os.date([format [, time]])
[edit]Return formatted date string, or table of time information. The format string has the same format as the C strftime() function.
Simple example:
> = os.date("%d.%m.%Y")
06.10.2012
If the format string is "*t" a table is returned containing the time information, e.g,
> table.foreach(os.date('*t'), print)
hour 14
min 36
wday 1
year 2003
yday 124
month 5
sec 33
day 4
isdst true
Above example using pairs() method:
> for k, v in pairs(os.date("*t")) do print(k, v) end
year 2012
day 1
min 54
wday 4
month 8
isdst true
yday 214
sec 39
hour 14
If the format is preceeded by "!" the time is converted to Coordinated Universal Time, e.g.,
> table.foreach(os.date('!*t'), print)
hour 21
min 36
wday 1
year 2003
yday 124
month 5
sec 42
day 4
isdst false
os.execute([command])
[edit]Execute an operating system shell command. This is like the C system() function. The system-dependent status code is returned.
> = os.execute("echo hello")
hello
0
> = os.execute("mmmmm") -- generate an error
'mmmmm' is not recognized as an internal or external command,
operable program or batch file.
1
With no argument, this command returns a non-zero value if an OS shell is presents or a zero value if one is not present.
> = os.execute() -- no argument
1
os.exit([code])
[edit]Calls the C function exit, with an optional code, to terminate the host program. The default value for code is the success code.
> os.exit(0) -- kill the Lua shell we are in and pass 0 back to parent shell
os.getenv(varname)
[edit]Returns the value of the process environment variable varname, or nil if the variable is not defined.
> = os.getenv("BANANA")
nil
> = os.getenv("USERNAME")
Nick
os.remove(filename)
[edit]Deletes the file with the given name. If this function fails, it returns nil, plus a string describing the error.
> os.execute("echo hello > banana.txt")
> = os.remove("banana.txt")
true
> = os.remove("banana.txt")
nil banana.txt: No such file or directory 2
os.rename(oldname, newname)
[edit]Renames file named old name to newname. If this function fails, it returns nil, plus a string describing the error.
> os.execute("echo hello > banana.txt")
> = os.rename("banana.txt", "apple.txt")
true
> = os.rename("banana.txt", "apple.txt")
nil banana.txt: No such file or directory 2
os.setlocale(locale [, category])
[edit]The function returns the name of the new locale, or nil if the request cannot be honoured.
os.time([table])
[edit]Given a formatted date table, as used by os.date() return the time in system seconds.
> t = os.date('*t') -- time now
> table.foreach(os.date('*t'), print)
hour 15
min 1
wday 1
year 2003
yday 124
month 5
sec 2
day 4
isdst true
> = os.time(t) -- time in system seconds
1052085659
> t.year = 2001 -- 2001, a Lua odyssey
> = os.time(t) -- time then
989013659
os.tmpname ()
[edit]Generate a name that can be used for a temporary file. This only generates a name, it does not open a file.
> = os.tmpname() -- on windows
\s2js.
> = os.tmpname() -- on debian
/tmp/lua_5xPi18
- ↑ See the following patch in the Mediawiki source code: https://gerrit.wikimedia.org/r/c/mediawiki/extensions/Scribunto/+/834623/4/includes/Engines/LuaCommon/lualib/strict.lua