Image source: Wikimedia Commons
Outline
Resources
Characteristics of the Lua language
Syntax
Syntax
Data types
Variables
Variables
Arithmetic and bitwise operators
Relational operators
Logical operators
Logical operators
Other operators
Conditions
Expressed using the familiar if, then, else and elseif keywords
if range < minRange then� -- ...�elseif range > maxRange then� -- ...�else� -- ...�end
Conditions
As with logical operators:
Loops - for (numeric)
for var = start, end[, step] do� -- body�end
var is the variable to be used as the loop index, initially set to start�The loop body is run�If var ~= end, step is added to var, and the process repeats (until var == end)
start, end and step must be numbers
step may be omitted, in which case it’s assumed to be equal to 1
Loops - for (numeric)
Go over each element of an array, one by one, and print it:�for i = 1, #elements do� print(elements[i])�end
Go over every odd-numbered element of an array (step = 2):�for i = 1, #elements, 2 do … end
Go over every element of an array in reverse order:�for i = #elements, 1, -1 do … end
Loops - for (iterator)
for index, value in ipairs(array) do� -- body�end
for key, value in pairs(table) do� -- body�end
Looping over ipairs(array) will run the loop for each element of array in order, setting index to the index of the element and value to the element itself.
Looping over pairs(table) will run the loop for each element of table, setting key to key the element is stored under and value to the element itself. The order of iteration is unspecified.
Loops - while, repeat
while #elements > 0 do� print(elements[#elements])� elements[#elements] = nil�end
repeat� print(elements[#elements])� elements[#elements] = nil�until #elements == 0
Loops - break
The break statement can be used to terminate any for, while or repeat loop early
for key, value in pairs(table) do� if key == searchedKey then� print(value)� break� end�end
Functions
A function is created using the keyword function, followed by a list of arguments, and the function definition. The resulting function is then assigned into a variable:�printArray = function(elements)� for _, element in ipairs(elements) do print(element) end�end
There is alternate syntax for this, that more resembles function declarations in C-like languages:�function printArray(elements)� for _, element in ipairs(elements) do print(element) end�end
Functions can be local variables as well:�local function printArray(elements)� -- ...�end
Functions - return value
function findIf(elements, predicate)� for _, element in ipairs(elements)� if predicate(element) then return element end� end�end
firstRoundSquare = findIf(� {1, 4, 9, 16, 25, 36, 49},� function(x)� return x % 5 == 0� end�)
Functions - multiple return values
function findIf(elements, predicate)� for index, element in ipairs(elements)� if predicate(element) then return index, element end� end�end
firstRoundSquareIndex, firstRoundSquare = findIf(� {1, 4, 9, 16, 25, 36, 49},� function(x)� return x % 5 == 0� end�)
Functions - optional parameters
As with unassigned variables, parameters not passed in are equal to nil�This can be used to emulate optional function parameters
function takeFiltered(elements, predicate, count)� local result = {}� for _, element in ipairs(elements) do� if predicate(element) then result[#result] = element end� if count ~= nil and #result == count then break end� end� return result�end��odds = takeFiltered({1, 2, 3, 4, 5, 6, 7, 8, 9}, isOdd)�firstTwoOdds = takeFiltered({1, 2, 3, 4, 5, 6, 7, 8, 9}, isOdd, 2)
Functions - variadic arguments
function concatenate(...)� local result = ””� for _, arg in ipairs({...}) do result = result .. arg end� return result�end
print(concatenate(”I caught ”, count, “ fish”))
Functions - closures
function counter(start, step)� return function() -- captures the variables start and step inside� local previousValue = start� start = start + step� return previousValue� end�end
oneCounter = counter(1, 1)�twoCounter = counter(10, 2)�print(oneCounter()) -- 1�print(twoCounter()) -- 10�print(oneCounter()) -- 2�print(twoCounter()) -- 12
Lua standard library
The host application that Lua is running in may choose to not include these libraries, therefore these functions may not always be available
Coroutines
Coroutines
coro = coroutine.create(function(v)� print(v) -- print the passed-in value� coroutine.yield(v + 4) -- yield v + 4 and wait for resume� return v * 5�end)��running, x = coroutine.resume(coro, 10) -- coro prints 10�-- running is true, because coro hasn’t finished yet�-- x is the value yielded from coro�print(running, x) -- true, 14�running, x = coroutine.resume(coro) -- coro finishes running�print(running, x) -- false, 50
Coroutines
counter = coroutine.create(function()� local x, continue = 0, true� while continue do� x = x + 1� continue = coroutine.yield(x)� end� return x�end)�print(coroutine.resume(counter)) -- true, 1�print(coroutine.resume(counter, true)) -- true, 2�print(coroutine.resume(counter, false)) -- false, 2�print(coroutine.resume(counter, false)) -- false, <error message>
Tables
Tables
Tables
Tables
Tables
Tables
Tables
Tables
bugatti = {� name = ”Bugatti Veyron”,� speed = 400,� drive = function(self, destination) --[[ … ]] end,� refuel = function(self) --[[ … ]] end�}�bugatti.drive(bugatti, prague)�bugatti:drive(prague) -- syntax sugar for the above line
Tables
Alternate syntax for defining functions in tables:�bugatti = {� name = ”Bugatti Veyron”,� speed = 400�}�function bugatti.drive(self, destination)� -- ...�end�-- or equivalently:�function bugatti:drive(destination)� -- parameter “self” is added implicitly�end
Metatables
__add | + | __band | & | __len | # |
__sub | - | __bor | | | __eq | == |
__mul | * | __bxor | ~ | __lt | < |
__div | / | __bnot | unary ~ | __le | <= |
__mod | % | __shl | << | __index | [] (read) |
__pow | ^ | __shr | >> | __newindex | [] (write) |
__unm | unary - | __concat | .. | __call | () |
__idiv | // | | | | |
Metatables
deepComparableArray = {� __eq = function(lhs, rhs)� -- compare arrays element by element� end�}�numbers = { 1, 3, 5 }�-- normally, two distinct arrays are never equal�print(tostring(numbers == { 1, 3, 5 })) -- false�setmetatable(numbers, deepComparableArray)�-- now deepComparableArray.__eq is used for this comparison instead�print(tostring(numbers == { 1, 3, 5 })) -- true
Metatables - __index
Metatables - __index
car = {}�function car:drive(destination) --[[ … ]] end�function car:refuel() --[[ … ]] end��bugatti = {� name = ”Bugatti Veyron”,� speed = 400�}�bugatti:drive(prague) -- error, cannot find bugatti.drive�setmetatable(bugatti, { __index = car })�bugatti:drive(prague) -- calls car:drive with self = bugatti
Metatables - __index
vehicle = {}�function vehicle:position() --[[ … ]] end
car = {}�function car:drive(destination) --[[ … ]] end�function car:refuel() --[[ … ]] end�setmetatable(car, { __index = vehicle })
bugatti = {� name = ”Bugatti Veyron”,� speed = 400�}�setmetatable(bugatti, { __index = car })�print(tostring(bugatti:position())) -- falls back to car:position, which falls back to vehicle:position
Userdata
Questions?