Hands on lua

48
Hands-on Lua Introductory course

description

An introductory course to this beautiful, efficient, totally free programming language and execution environment.

Transcript of Hands on lua

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