Top Banner
Hands-on Lua Introductory course
48

Hands on lua

Jun 15, 2015

Download

Technology

Javier Arauz

An introductory course to this beautiful, efficient, totally free programming language and execution environment.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Hands on lua

Hands-on Lua

Introductory course

Page 2: Hands on lua

Facts

• Developed at PUC Rio by Roberto Lerusalimschy et al

• Born as a C/C++ extension language

• Incorporates most innovations of RAD languages like Python, Ruby…

• Easily embeddable, lightweight and efficient

• Totally free and open license

Page 3: Hands on lua

Chunks• “a=1” in interactive mode

– each line in interactive mode is a chunck

• echo “a=1;b=2” > chunk.lua

– file chunk.lua is a chunk

• Running a chunk:

– “lua –lchunk” from command prompt

– “lua chunk.lua arg1 arg2” to pass command-line arguments

– dofile(“chunk.lua”) from within another chunk

Page 4: Hands on lua

Globals

• Define&use anywhere:– print(b) -- nil– b=10– print(b) -- 10

• To undefine:– b=nil

Page 5: Hands on lua

The interpreter

• Passing chunks:– lua –lchunk –e “a=math.sqrt(b)”

chunk.lua

• Passing command-line arguments:– lua –i –e “c=‘Hi !’” chunk.lua 1 2 3– print(arg[1])– print(arg[2])– print(arg[3])– print(arg[-1]) --???!!!

Page 6: Hands on lua

Types and Values

• From within the interpreter:– print(type(10))

• You can’t help trying these:– print(type(nil))– print(type(print)) --???!!!

Page 7: Hands on lua

Types and Values

• 6 built-in types:– nil (nil)

– boolean (true | false)

– number (any real number, usual formats allowed)

– string (any char sequence, 0 allowed!)

– table (more about these later)

– function (first-class values)

• 2 utility types:– userdata

– thread

Page 8: Hands on lua

Tables• From within the interpreter:

– t = {}– t[“key”] = “value”; print(t[“key”])– print(t[“otherkey”])– t[1] = “first”; print(t[1]); print(t[“key”])– print(t.key) --???!!!– t = { key=“value”, otherkey=“first” }– t = { key=“value”, 1=“first” } --???!!!– t = { key=“value”, [1]=“first” }– print(t.1) --???!!!

Page 9: Hands on lua

Arrays

• From within the interpreter:– t[1] = ‘a’; t[2] = ‘b’; t[3] = ‘c’– print(t[1] .. t[2] .. t[3])– print(t[-1]) (got what you expected?)– t[-1] = ‘z’– print(t[-1])– print(t) --???!!!– print(unpack(t))

Page 10: Hands on lua

Functions

• From within the interpreter:– function f ( a ) return a^2 end– print(f(2))

• Functions are first-class values:– t = {}– t[“square”] = f– print(t.square(2))

Page 11: Hands on lua

Some math…• Arithmetic operators:

+ - * / -()

• Relational operators:< > <= >= == ~=

• Logical operators:and or not– false and anything == false; true and

anything == anything– nil and anything == false– true or anything == true; false or anything

== anything– nil or anything == anything

Page 12: Hands on lua

Assignments

• From within the interpreter:– a = “Hi “ .. “there!”– a, b = 10, a– print(a, b)– a, b = b, a– print(a, b)– a, b, c = 0– print(a, b, c) --???!!!

Page 13: Hands on lua

Locals, blocks and scope

• From within the interpreter:– a = 10– local b = 2*a– print(a, b) --???!!!– do local b = 2*a; print(a,b) end

• What is a block?– a chunk is a block– a control sentence is a block– a function body is a block

Page 14: Hands on lua

if then else• From within the interpreter:

– if a < 0 then a = -a end– if a == 1 then– print(“first”)– else– if a < 0 then– error(“outofrange”)– else– print(a)– end– end

Page 15: Hands on lua

while and repeat

• From within the interpreter:– while a > 0 do– print(a)– a = a – 1– end– repeat– print(a)– a = a + 1– until a > 10

Page 16: Hands on lua

for

• From within the interpreter:– for i=1,10,2 do print(i) end– pets = { “cat”, “dog”, “bunny” }– for i,pet in pairs(pets) do print(i, pet) end– for i,pet in ipairs(pets) do print(i, pet) end– pets[“ops”] = “lion”– for i,pet in pairs(pets) do print(i, pet) end– for i,pet in ipairs(pets) do print(i, pet) end

Page 17: Hands on lua

break and return• From within the interpreter:

– for i,pet in pairs(pets) do– if pet==“lion” then break end– end– function findpet(name)– for i,pet in pairs(pets) do– if pet==name then return i,pet end– end– end– print(findpet(“lion”))

Page 18: Hands on lua

Formal and actual args

• From within the interpreter:– function f(a,b) print(a,b) end– f()– f(3)– f(3,4)– f(3,4,5)– f{3,4,5} --???!!!

Page 19: Hands on lua

Returning multiple values

• From within the interpreter:– function f(a,b) return a,b,5 end– a = f(3,4); print(a)– a,b = f(3,4); print(a,b)– a,b,c = f(3,4); print(a,b,c)– a,b,c,d = f(3,4); print(a,b,c,d)– a,b,c,d = f(1,2) , f(3,4); print(a,b,c,d)

--???!!!– t = { 1, 2 }; print(f(unpack(t)))

Page 20: Hands on lua

Variable number of args

• From within the interpreter:– function f(a, b, …) print(a,b,unpack(arg))

end– f(1)– f(1,2)– f(1,2,”Hi”, “there!”)

Page 21: Hands on lua

Named actual args• From within the interpreter:

– function p(name, addr, age, gender)

– if age > 120 then error(“U’re kidding me”) end

– record = { name=name, addr=addr, age=age, gender=gender }

– end

– p(“Johnny”, “Cash”, “male”, 90) --???!!!

– function P(r) p(r.name, r.addr, r.age, r.gender) end

– P{name=“Johnny”,addr=“Cash”,gender=“male”,age=90}

Page 22: Hands on lua

Functions as first-class values

• function f(a,b) print(a,b) end

• syntactic sugar for:– f = function (a,b) print(a,b) end

• some usages:– table.sort(pets, function (a,b) return (a>b) end)

– square = {

– x = 0; y = 0; size = 20;

– draw = function() some code end

– }

Page 23: Hands on lua

Closures

• From within the interpreter:– function newCounter ()– local i = 0– return function() i=i+1; return i end– end– c1 = newCounter()– c2 = newCounter()– print(c1(), c1(), c1())– print(c2(), c2())

Page 24: Hands on lua

Proper tail calls

• Check this C code:– int f ( char* state ) {– if (strcmp(state, “exit”))– return(0);– return f(state);– }– int result = f(“ooops”);

Page 25: Hands on lua

Iterators• From within the interpreter:

– function words ( filename )

– local file = io.open(filename)

– local line = file:read()

– local i = nil

– return function ()

– local b, e

– while not b do

– if not line then return nil end

– b,e = string.find(line, "[%w_]+", i)

– if b then

– i = e + 1; return string.sub(line, b, e)

– else

– i = nil; line = file:read()

– end

– end

– end

– end

– for word in words("chunk.lua") do print(word) end

Page 26: Hands on lua

Loading libraries

• Loading Lua libraries:– require “mypackage.mylib”

• Loading shared libraries:– local path =

“/usr/local/lua/lib/libluasocket.so”– local f = loadlib(path, “luaopen_socket”)– f() -- opens the library

Page 27: Hands on lua

Errors

• From within the interpreter:– file = assert(io.open(‘chunk.lua’, ‘r’))

• assert(chunk,msg) == if not chunk then error(msg)

• From within the interpreter:– local status, err =

– pcall(P{name=“Johnny”,address=“Cash”,age=150, gender=“male”})

– if not status then print(err) end

Page 28: Hands on lua

Coroutines

• From within the interpreter:– co = coroutine.create(function()

– for i=1,10 do

– print("co", i)

– coroutine.yield()

– end

– end)

– coroutine.resume(co)

– coroutine.resume(co)

– coroutine.resume(co)

Page 29: Hands on lua

Metatables• From within the interpreter:

– Complex = {}– function Complex.new (c)– setmetatable(c, Complex); return c– end– function Complex.__add (a,b)– return Complex.new{r=a.r+b.r, i=a.i+b.i}– end– c = Complex.new{r=1,i=2} +

Complex.new{r=3,i=4}– print(unpack(c))

Page 30: Hands on lua

Metatables

Key Value

Key Value

__index

__newindex

__tostring

setmetatable(t,mt)

t

mt

Page 31: Hands on lua

Polymorphism

• From within the interpreter:– print(c)– function Complex.__tostring(c)– return tostring(c.r) .. ‘+’ .. tostring(c.i)

.. ‘i’– end– print(c)

Page 32: Hands on lua

Inheritance• From within the interpreter:

– Phone = {}

– Phone.keypad = {[1]=“1”, [2]=“2”}

– function Phone.dial ( keys ) print(keys) end

– CarPhone = {}

– CarPhone.mike = io

– CarPhone.dir = { Johnny = “112”, Cash = “211” }

– function CarPhone.voice_dial ()

– CarPhone.dial(CarPhone.dir[CarPhone.mike.read()])

– end

Page 33: Hands on lua

Inheritance

• From within the interpreter:– CarPhone.voice_dial() ???!!!– Phone.__index = Phone– setmetatable(CarPhone, Phone)– CarPhone.voice_dial()

– Phone.speaker = io– CarPhone.speaker.write(“Beeeeeeeeep”)

Page 34: Hands on lua

Overloading

• From within the interpreter:– CellPhone = {– dial = function ( keys ) error(“no link”)

end– }– setmetatable(CellPhone, Phone)– CellPhone.dial(“112”)

• There is no argument-based overloading!

Page 35: Hands on lua

Metamethods

• List of metamethods:– add (+)– sub (-)– mul (*)– div (/)– mod (%)– pow (^)– unm (-)– concat (..)– len (#)

– eq (=)– lt (<)– le (<=)– index ([])– newindex– call (())

Page 36: Hands on lua

The environment• From within the interpreter:

– print(_G._G == _G) ???!!!– for gv in pairs(_G) do print(gv) end– for obj in pairs(_G) do– if string.find(obj, “Phone$”) then– _G[obj].dial(“112”)– end– end– setmetatable(_G, {– __newindex = function(_,gv) error(“read only!”) end,– })– newglobal = “oopss”

Page 37: Hands on lua

More environments• From within the interpreter:

– ctx = { ignore_case=true }– function my_find ( string, regexp )– if ctx and ctx.ignore_case then– return string.find(string.lower(string), regexp)– else– return string.find(string, regexp)– end– end– print(my_find(“Hi there!”, “hi”))

– do– local myG = { ctx = {} }– setmetatable(myG, {__index=_G})– setfenv(my_find, myG)– end– print(my_find(“Hi there!”, “hi”))– setfenv(my_find, _G)

Page 38: Hands on lua

OO Programming

• From within the interpreter:– function Phone:new (obj)– obj = obj or {}– setmetatable(obj, self)– self.__index = self– return obj– end– my_phone = Phone:new()– my_phone:dial(“112”) --???!!!

Page 39: Hands on lua

Metatables in OO Programming

Key Value

Key Value

__tostring

__newindex

__index

new

obj

Phone

…setmetatable(obj,self)…

Page 40: Hands on lua

C API: the stack• C to Lua:

– void lua_pushnil– void lua_pushboolean– void lua_pushnumber– void lua_pushstring– void lua_pushlstring

• Lua to C:– int lua_toboolean– double lua_tonumber– const char* lua_tostring– size_t lua_strlen– void lua_gettable– void lua_settable

C running image

Data segment

Code segment

stack

C code Lua lib

Page 41: Hands on lua

C API: other stack functions– lua_open to create a Lua state

– luaL_loadfile to read a Lua script into memory

– lua_pcall to run a Lua chunk in protected mode

– lua_getglobal to read lua global environment

– lua_setglobal to write lua global environment

– lua_pop to remove a value from the stack

– lua_newtable to create a new table on the stack

– lua_close to end a running state

Page 42: Hands on lua

C API: the stack from the other side

• Pre-C to Lua:– void

lua_pushcfunction

• C to Lua the right way™:– struct luaL_reg– void luaL_openlib

• Lua to C the right way™:– loadlib()

C running image

Data segment

Code segment

stack

C code Lua lib

Page 43: Hands on lua

C API: Example• #include <dirent.h>• #include <errno.h>• static int l_dir (lua_State *L) {• DIR *dir; struct dirent *entry; int i;• const char *path = luaL_checkstring(L, 1);• /* open directory */• dir = opendir(path);• if (dir == NULL) { /* error opening the directory? */• lua_pushnil(L); /* return nil and ... */• lua_pushstring(L, strerror(errno)); /* error message */• return 2; /* number of results */• }• /* create result table */• lua_newtable(L);• i = 1;• while ((entry = readdir(dir)) != NULL) {• lua_pushnumber(L, i++); /* push key */• lua_pushstring(L, entry->d_name); /* push value */• lua_settable(L, -3);• }• closedir(dir);• return 1; /* table is already on top */• }

Page 44: Hands on lua

Example: application configuration

• In file “app.conf”:– Rule{– name = “HTTP”,– ports={– dest={80, 8080},– },– signatures = { “GET “ .. URL .. “ HTTP 1.1\n” }– }

– Rule{ name = “FTP”, … }– Rule{ name = “SSH”, … }

Page 45: Hands on lua

Example: application configuration• In file “main.c”:

– typedef struct { char*name, int* ports, char** signatures } Rule;– static Rule rules[256];– static int numRules = 0;– static int readRule ( lua_State* L ) {– if (numRules == sizeof(rules)) return 0;– Rule rule;– rule.name = lua_tostring(L, 1);– rule.ports = …– rule.signatures = …– rules[numRules++] = rule;– return 0;– }– …– int main ( int argc, char** argv ) {– lua_State* L = lua_open();– luaL_loadfile(L, “app.conf”);– lua_pushcfunction(L, readRule);– lua_setglobal(L, “Rule”);– lua_pcall(L, 0, 0, 0);– }

Page 46: Hands on lua

Example: application configuration

• In file “app.conf”:– function dbIterator ( table )

– local dbConn = lua.sql.connect(db_url)

– local cursor = dbConn.execute(“SELECT * FROM “ .. table)

– return function() return cursor.next() end

– end

–– for dbRule in dbIterator do Rule(dbRule) end

Page 47: Hands on lua

Example: transforms

Page 48: Hands on lua

References• http://www.lua.org

– http://www.lua.org/manual Reference Manual– http://www.lua.org/pil Text Book– http://www.luaforge.net Code Repository– http://www.keplerproject.org It all begun here