Lua is a very fast, elegant and powerful dynamic language. It’s an excellent tool for robust applications or slim embedded systems. It found a niche in game development with big names such as “Grim Fandango”, “World of Warcraft” and “Angry Birds”. This talk will present what makes Lua different from other interpreted languages, the evolution of the Lua ecosystem, some key concepts of the language, and show you why Lua is the next language to add to your skill set.
14. Hackference 2016 @etiene_d
"Since Lua itself is so
simple, it tends to
encourage you to solve
problems simply."
Ragnar Svensson - Lead Developer at King
(Lua Workshop Oct 15 2015)
19. @etiene_dHackference 2016
• It looks cool
(I heard you could make games with it)
• It’s made in my home country
(In my university to be more precise)
• It’s easy to learn
Better Reasons
20. @etiene_dHackference 2016
• The index starts at 1
• There’s no continue
• The non-equality operator is ~=
• null is nil
• Comments are - -
• Only nil and false are equivalent to false
• Functions can genuinely return multiple values
• Variables are global by default
• Pattern matching is not regular expression
• The concatenation operator is ..
What’s different
21. @etiene_dHackference 2016
Quick idioms
• a, b = b, a
• There’s no ternary operator but you can
return x==1 and “yes” or “no”
• The access to local variables is faster than to global
local match = string.match
25. @etiene_dHackference 2016
• The only way to structure data
• Array, dictionary, object, list, queue, module…
• Any value can be a key, except nil and nan
• Behind the scenes: array or hash table
• Passed as reference
• The length operator: #
• pairs(t) x ipairs(t)
Tables Tables Tables
27. @etiene_dHackference 2016
• The only way to structure data
• Array, dictionary, object, list, queue, module…
• Any value can be a key, except nil
• Behind the scenes: array or hash table
• Passed as reference
• The length operator: #
• pairs(t) x ipairs(t)
Tables
29. @etiene_dHackference 2016
local a = { 1, 3, 5, 7, 9}
local sum = 0
for i=1,#a do
sum = sum + a[i]
end
print(sum) -- 25
Tables
local a = {}
a[1] = 1
a[2] = 3 -- etc
local sum = 0
for _, x in ipairs(a) do
sum = sum + x
end
print(sum)
30. @etiene_dHackference 2016
local a = { 1, 3, 5, 7, 9}
local sum = 0
for i=1,#a do
sum = sum + a[i]
end
print(sum) -- 25
local point = { x = 10, y = 25}
print(point[“x”], point[“y”]) -- 10 25
print(point.x, point.y) -- 10 25
print(point[x], point[y]) -- nil nil (attention!)
Tables
31. @etiene_dHackference 2016
local a = { 1, 3, 5, 7, 9}
local sum = 0
for i=1,#a do
sum = sum + a[i]
end
print(sum) -- 25
local point = { x = 10, y = 25}
print(point[“x”], point[“y”]) -- 10 25
print(point.x, point.y) -- 10 25
print(point[x], point[y]) -- nil nil (attention!)
-- sets and multisets
local ips = {[“5.101.112.0”] = true, [“213.35.128.0”] = true}
local conns = {[“5.101.112.0”] = 5, [“213.35.128.0”] = 2}
Tables
32. @etiene_dHackference 2016
-- Cipher module
--[[ Based on algorithms/caesar_cipher.lua
by Roland Yonaba ]]
local cipher = {}
local function ascii_base(s)
return s:lower() == s and ('a'):byte() or ('A'):byte()
end
function cipher.caesar( str, key )
return str:gsub('%a', function(s)
local base = ascii_base(s)
return string.char(((s:byte() - base + key) % 26) + base)
end)
end
return cipher
Modules
33. @etiene_dHackference 2016
-- Cipher module
--[[ Based on algorithms/caesar_cipher.lua
by Roland Yonaba ]]
local cipher = {}
local function ascii_base(s)
return s:lower() == s and ('a'):byte() or ('A'):byte()
end
function cipher.caesar( str, key )
return str:gsub('%a', function(s)
local base = ascii_base(s)
return string.char(((s:byte() - base + key) % 26) + base)
end)
end
return cipher
Modules
34. @etiene_dHackference 2016
-- Cipher module
--[[ Based on algorithms/caesar_cipher.lua
by Roland Yonaba ]]
local cipher = {}
local function ascii_base(s)
return s:lower() == s and ('a'):byte() or ('A'):byte()
end
function cipher.caesar( str, key ) --cipher.caesar = function(str,key)
return str:gsub('%a', function(s) --cipher["caesar"] = function(str,key)
local base = ascii_base(s)
return string.char(((s:byte() - base + key) % 26) + base)
end)
end
return cipher
Modules
public
35. @etiene_dHackference 2016
-- Cipher module
--[[ Based on algorithms/caesar_cipher.lua
by Roland Yonaba ]]
local cipher = {}
local function ascii_base(s)
return s:lower() == s and ('a'):byte() or ('A'):byte()
end
function cipher.caesar( str, key )
return str:gsub('%a', function(s)
local base = ascii_base(s)
return string.char(((s:byte() - base + key) % 26) + base)
end)
end
return cipher
Modules
private
36. @etiene_dHackference 2016
-- Cipher module
--[[ Based on algorithms/caesar_cipher.lua
by Roland Yonaba ]]
local cipher = {}
local function ascii_base(s)
return s:lower() == s and ('a'):byte() or ('A'):byte()
end
function cipher.caesar( str, key )
return str:gsub('%a', function(s)
local base = ascii_base(s)
return string.char(((s:byte() - base + key) % 26) + base)
end)
end
return cipher
Modules
local c = require “cipher”
print(c.caesar(“test”,3) -- whvw
37. @etiene_dHackference 2016
• Overload operators
• Override built-in functions such as tostring
• Treat missing fields or intercept new field creation
• Call table as a function
• Metamethods:
__add, __sub, __mul, __div, __mod, __pow, __unm,
__concat, __len, __eq, __lt, __le, __index, __newindex,
__call, __tostring, __ipairs, __pairs, __gc
Metatables
38. @etiene_dHackference 2016
local mt = {}
local function new(r, i)
return setmetatable({ real = r or 0, im = i or 0}, mt)
end
local function is_complex(v)
return getmetatable(v) == mt
end
local function add(c1, c2)
if not is_complex(c1) then
return new(c2.real + c1, c2.im)
elseif not is_complex(c2) then
return new(c1.real + c2, c1.im)
end
return new(c1.real + c2.real, c1.im + c2.im)
end
local function tos(c)
return tostring(c.real) .. "+".. tostring(c.im) .. "i"
end
mt.__add = add
mt.__tostring = tos
Complex numbers
39. @etiene_dHackference 2016
local mt = {}
local function new(r, i)
return setmetatable({ real = r or 0, im = i or 0}, mt)
end
local function is_complex(v)
return getmetatable(v) == mt
end
local function add(c1, c2)
if not is_complex(c1) then
return new(c2.real + c1, c2.im)
elseif not is_complex(c2) then
return new(c1.real + c2, c1.im)
end
return new(c1.real + c2.real, c1.im + c2.im)
end
local function tos(c)
return tostring(c.real) .. "+".. tostring(c.im) .. "i"
end
mt.__add = add
mt.__tostring = tos
Complex numbers
40. @etiene_dHackference 2016
local mt = {}
local function new(r, i)
return setmetatable({ real = r or 0, im = i or 0}, mt)
end
local function is_complex(v)
return getmetatable(v) == mt
end
local function add(c1, c2)
if not is_complex(c1) then
return new(c2.real + c1, c2.im)
elseif not is_complex(c2) then
return new(c1.real + c2, c1.im)
end
return new(c1.real + c2.real, c1.im + c2.im)
end
local function tos(c)
return tostring(c.real) .. "+".. tostring(c.im) .. "i"
end
mt.__add = add
mt.__tostring = tos
Complex numbers
41. @etiene_dHackference 2016
local mt = {}
local function new(r, i)
return setmetatable({ real = r or 0, im = i or 0}, mt)
end
local function is_complex(v)
return getmetatable(v) == mt
end
local function add(c1, c2)
if not is_complex(c1) then
return new(c2.real + c1, c2.im)
elseif not is_complex(c2) then
return new(c1.real + c2, c1.im)
end
return new(c1.real + c2.real, c1.im + c2.im)
end
local function tos(c)
return tostring(c.real) .. "+".. tostring(c.im) .. "i"
end
mt.__add = add
mt.__tostring = tos
Complex numbers
42. @etiene_dHackference 2016
local mt = {}
local function new(r, i)
return setmetatable({ real = r or 0, im = i or 0}, mt)
end
local function is_complex(v)
return getmetatable(v) == mt
end
local function add(c1, c2)
if not is_complex(c1) then
return new(c2.real + c1, c2.im)
elseif not is_complex(c2) then
return new(c1.real + c2, c1.im)
end
return new(c1.real + c2.real, c1.im + c2.im)
end
local function tos(c)
return tostring(c.real) .. "+".. tostring(c.im) .. "i"
end
mt.__add = add
mt.__tostring = tos
Complex numbers
43. @etiene_dHackference 2016
local mt = {}
local function new(r, i)
return setmetatable({ real = r or 0, im = i or 0}, mt)
end
local function is_complex(v)
return getmetatable(v) == mt
end
local function add(c1, c2)
if not is_complex(c1) then
return new(c2.real + c1, c2.im)
elseif not is_complex(c2) then
return new(c1.real + c2, c1.im)
end
return new(c1.real + c2.real, c1.im + c2.im)
end
local function tos(c)
return tostring(c.real) .. "+".. tostring(c.im) .. "i"
end
mt.__add = add
mt.__tostring = tos
>local c1 = new(2,3)
>print( c1 + 5 )
7+3i
Complex numbers
44. @etiene_dHackference 2016
local square = { x = 10, y = 20, side = 25 }
function square.move(obj, dx, dy)
obj.x = obj.x + dx
obj.y = obj.y + dy
end
function square:area()
return self.side ^ 2
end
print(square:area()) -- 625
Objects
45. @etiene_dHackference 2016
local square = { x = 10, y = 20, side = 25 }
function square.move(obj, dx, dy)
obj.x = obj.x + dx
obj.y = obj.y + dy
end
function square:area()
return self.side ^ 2
end
print(square:area()) -- 625
Objects
46. @etiene_dHackference 2016
local square = { x = 10, y = 20, side = 25 }
function square.move(obj, dx, dy)
obj.x = obj.x + dx
obj.y = obj.y + dy
end
function square:area()
return self.side ^ 2
end
print(square:area()) -- 625
Objects
47. @etiene_dHackference 2016
local square = { x = 10, y = 20, side = 25 }
function square.move(obj, dx, dy)
obj.x = obj.x + dx
obj.y = obj.y + dy
end
function square:area()
return self.side ^ 2
end
print(square:area()) -- 625
Objects
48. @etiene_dHackference 2016
local square = { x = 10, y = 20, side = 25 }
function square.move(obj, dx, dy)
obj.x = obj.x + dx
obj.y = obj.y + dy
end
function square:area()
return self.side ^ 2
end
print(square:area()) -- 625
local square2 = (x = 30, y = 5, side = 10}
print(square.area(square2)) -- 100
Objects
49. @etiene_dHackference 2016
local Square = {}
function Square:new(x, y, side)
local o = { x = x, y = y, side = side}
setmetatable(o, self)
self.__index = self
return o
end
function Square:move(dx, dy)
self.x = self.x + dx
self.y = self.y + dy
end
function Square:area()
return self.side ^ 2
end
return Square
Object Orientation
50. @etiene_dHackference 2016
local Square = {}
function Square:new(x, y, side)
local o = { x = x, y = y, side = side}
setmetatable(o, self)
self.__index = self
return o
end
function Square:move(dx, dy)
self.x = self.x + dx
self.y = self.y + dy
end
function Square:area()
return self.side ^ 2
end
return Square
Object Orientation
51. @etiene_dHackference 2016
local Square = {}
function Square:new(x, y, side)
local o = { x = x, y = y, side = side}
setmetatable(o, self)
self.__index = self
return o
end
function Square:move(dx, dy)
self.x = self.x + dx
self.y = self.y + dy
end
function Square:area()
return self.side ^ 2
end
return Square
Object Orientation
52. @etiene_dHackference 2016
local Square = {}
function Square:new(x, y, side)
local o = { x = x, y = y, side = side}
setmetatable(o, self)
self.__index = self
return o
end
function Square:move(dx, dy)
self.x = self.x + dx
self.y = self.y + dy
end
function Square:area()
return self.side ^ 2
end
return Square
Object Orientation
53. @etiene_dHackference 2016
local Square = {}
function Square:new(x, y, side)
local o = { x = x, y = y, side = side}
setmetatable(o, self)
self.__index = self
return o
end
function Square:move(dx, dy)
self.x = self.x + dx
self.y = self.y + dy
end
function Square:area()
return self.side ^ 2
end
return Square
local Square = require “square”
local s1 = Square:new(10,20,25)
local s2 = Square:new(30,5,10)
print(s1:area()) -- 625
print(s2:area()) -- 100
Object Orientation