lua first steps
DESCRIPTION
A quick overview of Lua, an overview over the syntax, what it is good at, why it's getting more popular, and most of all: why it rocks!TRANSCRIPT
Lua
Topics
• History + background
• Key features
• Syntax
• Tables
• Embedding
• Usecase
Topics
• History + background
• Key features
• Syntax
• Tables
• Embedding
• Usecase
Pictures
Code
1977-1992Trade Barriers
Pontifícia Universidade Católica do Rio de
Janeiro
PUC
SOL (Simple Object Language)
DEL (Data Entry Language)+
=Lua
Sol
Lua
• Easy to write and understand (so no Lisp, TCL or Scheme), Python wasn’t good enough yet
• Diverse collection of computers (so highly portable, not -nix only)
• Should be provided as a library with a C-API
• Scheme
• Modula
• CLU
• C++
• SNOBOL
• AWK
Influences
in use by
etc.
Robust
Fast
Portable
Embeddable
Powerful (yet simple)
Small
Free
Awesome
Syntax
if/then
if true == false then print "foobar";else print "Ponies";end
while
while true do print "Ponies!";end
repeat/until
repeat line = os.read()until line ~= ""print "Ponies";
Types
print(type("Ponies")) --> stringprint(type(10.4*3)) --> numberprint(type(print)) --> functionprint(type(type)) --> functionprint(type(true)) --> booleanprint(type(nil)) --> nilprint(type(type(X))) --> string
Types
print(type(a)) --> nila = 10print(type(a)) --> numbera = "Ponies!!"print(type(a)) --> stringa = print -- yes, this is valid!a(type(a)) --> function
More
• ~= == !=
• ‘local’ for local variables (garbage collection)
• bytecode execution on Lua VM (.luac)
Tables
Tables
Functions
Functions are anonymous, and are pointers to variables
a = {p = print} -- create a tablea.p("Ponies!") --> Ponies!print = math.sin -- `print' now refers to the 'sin' functiona.p(print(1)) --> 0.841470sin = a.p -- `sin' now refers to the print functionsin(10, 20) --> 10 20
Tables
• Can be used to define anything you want
• Classes, objects, namespaces, you name it
• The only complex data structure available
Tables
a = {} -- create a table and reference it in 'a'k = "x"a[k] = 10 -- new entry, with key="x" and value=10a[20] = "Ponies!!1" -- new entry, key=20 and value="Ponies!!1"print(a["x"]) --> 10k = 20print(a[k]) --> "Ponies!!1"a["x"] = a["x"] + 1 -- increments entry "x"print(a["x"]) --> 11print(a.x) --> 11
As array
Tables
point = { x = 10, y = 20 } -- Create new tableprint(point["x"]) -- Prints 10print(point.x) -- Prints 10
As structures (objects)
TablesAs namespace
Point = {}Point.new = function (x, y) return {x = x, y = y}endPoint.set_x = function (point, x) point.x = xend
MetaTables!
• The power to override events on tables, built into the interpreter
• Useful for namespacing, classes, inheritance, etc.
MetaTables!
t1 = {a = "Ponies!"} -- t1 is a table with one name-value pair.t2 = {} -- t2 is an empty table.setmetatable(t1, t2) -- t2 is t1's metatable.t3 = {c = "Rainbows!"} -- t3 is just another table like t1.
t2.__index = t3 -- when a lookup fails in t1, t2 will -- look for a value in t3.
print(t1.a) -- Ponies!print(t1.b) -- nilprint(t1.c) -- Rainbows!
MetaTables!
t1 = {a = "Ponies!"} -- t1 is a table with one name-value pair.t2 = {} -- t2 is an empty table.setmetatable(t1, t2) -- t2 is t1's metatable.t3 = {c = "Rainbows!"} -- t3 is just another table like t1.
t2.__index = function (t, k) return k -- When no value is found, return the keyend
print(t1.a) -- Ponies!print(t1.b) -- bprint(t1.c) -- c
Another example
Embedding
Python examplePyLux
import pylux
# Shorthand to run a Lua script with "lux('script')"def lux(script): pylux.eval("gv", "dostring", script)
# Shorthand to define a Python proc as callback for Luadef luxcb(name,func): pylux.eval("gvc", "setglobal", name, func)
luxGlobals=[]luxcb("luxAppend", luxGlobals.append)lux(""" for i,v in globals() do luxAppend(i) end""")luxGlobals.sort()print luxGlobals
Ruby examplerubyluabridge et all
require 'rubyluabridge'l = Lua::State.new # Create a new state for the bridge # (this is your 'sandbox')
l.eval("return 1") # 1l.n = 5l.eval("return n") # 5l.eval("s='Ponies!'")print l.s # Ponies!
Usecase
Background• Medianetwork
• max 10gbit/s
• Millions of request/day (10 million+)
• Only binary data
• Custom solution built in CProxy (old)
• Needed new feature set
• API with several subsystems
Background
• Needed easy maintenance
• Scalable, lightweight, fast
• Future proof
• Features!
• No exposure of backend storage
Decisions
• nginx
• mod_lua
• mod_cache
• mod_proxy
• LuaSockets
Bitmovr.lua
• Lua
• Memcached
• Supports only GET
• Proxy
• Using filesinks => bitmovr
Architecture
edge
MediaTool Castor
Loadbalancer
Loadbalancer
lighttpdlighttpdlighttpdlighttpdlighttpdlighttpdnginx
LuaSocket-- include librariessocket = require("socket");
-- create a TCP socket and bind it to the local host at the given portserver = assert(socket.bind('0.0.0.0',50000))
-- loop forever waiting for clientswhile 1 do
-- wait for a connection from any client local client = server:accept()
-- make sure we don't block waiting for this client's line client:settimeout(10)
-- receive the line local line, err = client:receive()
-- if there was no error, send it back to the client if not err then
-- send the same response as was send client:send(line);
-- close the connection client:close() endend
LTN12Sinks, Pumps, Filters, Chains, etc.
-- load the ltn12 modulelocal ltn12 = require("ltn12")
-- copy a fileltn12.pump.all( ltn12.source.file(io.open("original.png")), ltn12.sink.file(io.open("copy.png")))
LTN12Sinks, Pumps, Filters, Chains, etc.
local outputSink = socket.sink("close-when-done", client)
local r, c, h = socket.http.request{ sink = outputSink, method = 'GET', url = storageLocation, redirect = true}
Conclusion
• Fast, simple, elegant, flexible
• A bit of a hurdle
• Sandboxing is interesting
Questions?