Get started with


Etiene Dalcol
@etiene_d
@etiene_dHackference 2016
@etiene_d
@etiene_dHackference 2016
A Lua MVC web framework

sailorproject.org
@etiene_dHackference 2016
@etiene_dHackference 2016
luaconf.com
@etiene_dHackference 2016
What’s Lua
Why Lua
Key Concepts
@etiene_dHackference 2016
@etiene_dHackference 2016
• Dynamic duck-typed language
• Multi-paradigm
• procedural, OO, functional
• Garbage collection
• Coroutines
• First-class functions
• Lexical scoping
• Proper tail calls
• MIT License
What is Lua?
@etiene_dHackference 2016
Why Lua?
Powerful.
@etiene_dHackference 2016
Why Lua?
Size
(docs included)
First-class functions

+
Lexical scoping
+
Metatables
Native C API
276 Kb
Object Orientation
Ada, Fortran, Java,
Smalltalk, C#, Perl,
Ruby etc.
+
@etiene_dHackference 2016
Simple.Powerful.
Why Lua?
@etiene_dHackference 2016
_G
_VERSION
assert
collectgarbage
dofile
error
getmetatable
ipairs
load
loadfile
next
pairs
pcall
print
rawequal
rawget
rawlen
rawset
require
select
setmetatable
tonumber
tostring
type
xpcall
bit32.arshift
bit32.band
bit32.bnot
bit32.bor
bit32.btest
bit32.bxor
bit32.extract
bit32.lrotate
bit32.lshift
bit32.replace
bit32.rrotate
bit32.rshift
coroutine.create
coroutine.resume
coroutine.running
coroutine.status
coroutine.wrap
coroutine.yield
debug.debug
debug.getuservalue
debug.gethook
debug.getinfo
debug.getlocal
debug.getmetatable
debug.getregistry
debug.getupvalue
debug.setuservalue
debug.sethook
debug.setlocal
debug.setmetatable
debug.setupvalue
debug.traceback
debug.upvalueid
debug.upvaluejoin
io.close
io.flush
io.input
io.lines
io.open
io.output
io.popen
io.read
io.stderr
io.stdin
io.stdout
io.tmpfile
io.type
io.write
file:close
file:flush
file:lines
file:read
file:seek
file:setvbuf
file:write
math.abs
math.acos
math.asin
math.atan
math.atan2
math.ceil
math.cos
math.cosh
math.deg
math.exp
math.floor
math.fmod
math.frexp
math.huge
math.ldexp
math.log
math.max
math.min
math.modf
math.pi
math.pow
math.rad
math.random
math.randomseed
math.sin
math.sinh
math.sqrt
math.tan
math.tanh
os.clock
os.date
os.difftime
os.execute
os.exit
os.getenv
os.remove
os.rename
os.setlocale
os.time
os.tmpname
package
package.config
package.cpath
package.loaded
package.loadlib
package.path
package.preload
package.searchers
package.searchpath
string.byte
string.char
string.dump
string.find
string.format
string.gmatch
string.gsub
string.len
string.lower
string.match
string.rep
string.reverse
string.sub
string.upper
table.concat
table.insert
table.pack
table.remove
table.sort
table.unpack
@etiene_dHackference 2016
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)
@etiene_dHackference 2016
Fast.Simple.Powerful.
Why Lua?
@etiene_dHackference 2016
http://www.humbedooh.com/presentations/ACNA%20-%20mod_lua.odp Introducing mod_lua by Daniel Gruno
@etiene_dHackference 2016
My Reasons
• It looks cool
(I heard you could make games with it)
Better
@etiene_dHackference 2016
Better Reasons
• 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)
@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
@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
@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
@etiene_dHackference 2016
Using Lua: three approaches
Embedded Scripting General-purpose
@etiene_dHackference 2016
Getting Lua
• lua.org > download
• OS package manager
• apt-get install lua
• brew install lua
LuaRocks
• luarocks.org > install
• OS package manager
• apt-get install luarocks
@etiene_dHackference 2016
Key Concepts
@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
@etiene_dHackference 2016
Tables
Header
key value
“x” 9.2
nil
value
100
200
300
nil
@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
@etiene_dHackference 2016
Tables
local a = { 1, 3, 5, 7, 9}
local sum = 0
for i=1,#a do
sum = sum + a[i]
end
print(sum) -- 25
@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)
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
Thank you!
etiene.net

github.com/Etiene/
dalcol@etiene.net
@etiene_d
@etiene_dHackference 2016
Going further
@etiene_dHackference 2016


• Hardware
• eLua: http://www.eluaproject.net/
• nodemcu: http://nodemcu.com

• Scientific Computing and Machine Learning
• SciLua http://www.scilua.org/
• Torch: http://torch.ch
• GSL Shell: http://www.nongnu.org/gsl-shell/
Cool tools in Lua
@etiene_dHackference 2016


• Game development
• Love2D: https://love2d.org/
• Defold: http://www.defold.com/
• Cocos2d: http://www.cocos2d-x.org/
• Corona: https://coronalabs.com

• Web development
• (Nginx) OpenResty http://openresty.org
• Luvit: https://luvit.io/
• Lapis: http://leafo.net/lapis/
• Sailor: http://sailorproject.org/
• Starlight: http://starlight.paulcuth.me.uk/
Cool tools in Lua
@etiene_dHackference 2016
• IDE
• ZeroBrane Studio: http://studio.zerobrane.com/

• Testing
• Busted: http://olivinelabs.com/busted/
• Package management
• LuaRocks http://luarocks.org

• Misc
• Moonscript: http://moonscript.org/
• Awesome Lua:

https://github.com/LewisJEllis/awesome-lua
Cool tools in Lua
@etiene_dHackference 2016
• Community
• Lua mail list: http://www.lua.org/lua-l.html
• #LuaLang on Twitter
• Lua community blog: http://lua.space
• Lua’s subreddit: http://reddit.com/r/lua
• Lua’s IRC channel: irc.freenode.net #lua
• Books
• Programming in Lua: http://www.lua.org/pil/
• Lua Programming Gems: http://www.lua.org/gems/
• Misc
• CodeCombat: https://codecombat.com
Resources
Thank you!
etiene.net

github.com/Etiene/
dalcol@etiene.net
@etiene_d

Get started with Lua - Hackference 2016