Lua中文教程(Programming in Lua)


Programming in Lua Copyright ® 2005, Translation Team, www.luachina.net Programming in Lua Programming in Lua Roberto Ierusalimschy www.luachina.net Simple is beautiful Copyright ® 2005, Translation Team, www.luachina.net Programming in Lua i Copyright ® 2005, Translation Team, www.luachina.net Programming in Luawww.luachina.netMr. Roberto IerusalimschyMr. Roberto Ierusalimschy Copyright © 2003-2004 Roberto Ierusalimschy. All rights reserved. This online book is for personal use only. It cannot be copied to other web sites or further distributed in any form. Programming in Lua i Copyright ® 2005, Translation Team, www.luachina.net C/C++Java C#VBFortranPerlTclRubyForthPython Lua hacker BrainFuck1Hello World-- >+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[ -]>++++++++[<++++>-]<.#>+++++++++++[<+++++>-]<.>++++++++[<+ ++>-]<.+++.------.--------.[-]>++++++++[<++++>-]<+.[-]+++++ +++++. Java Perl C/C++ web Lua C C/C++ Lua Lua ANSI C C Lua Lua Python Lua Lua 1 Brain Fuckhttp://www.muppetlabs.com/~breadbox/bf/ Programming in Lua ii Copyright ® 2005, Translation Team, www.luachina.net www.luachina.net -- file: 'thanks.lua' -- desc: to print the list of the contributing guys function list_iter (t) local i = 0 local n = table.getn(t) return function () i = i + 1 if i <= n then return t[i] end end end helpful_guys = { "--------", "buxiu", "", "zhang3", "morler", "lambda", "sunlight", "\n", "--------", "", "doyle", "flicker", "", "zhang3", "Kasi", "\n" } for e in list_iter(helpful_guys) do print(e) end www.luachina.net 2005 7 26 pdf Programming in Lua iii Copyright ® 2005, Translation Team, www.luachina.net ........................................................................................................................................ i ................................................................................................................................................ i .............................................................................................................................................. iii ................................................................................................................................. 1 0 ................................................................................................................................. 1 0.1 .................................................................................................................................... 1 0.2 Lua....................................................................................................................... 2 0.3 Lua................................................................................................................... 3 0.4 ........................................................................................................................ 3 0.5 ............................................................................................................................ 3 0.6 .................................................................................................................................... 4 1 ................................................................................................................................. 5 1.1 Chunks................................................................................................................................. 5 1.2 ............................................................................................................................ 7 1.3 ............................................................................................................................ 7 1.4 ........................................................................................................................ 7 2 ......................................................................................................................... 9 2.1 Nil........................................................................................................................................ 9 2.2 Booleans .............................................................................................................................. 9 2.3 Numbers............................................................................................................................. 10 2.4 Strings................................................................................................................................10 2.5 Functions ........................................................................................................................... 12 2.6 Userdata and Threads ........................................................................................................ 12 3 ........................................................................................................................... 13 3.1 ...................................................................................................................... 13 3.2 ...................................................................................................................... 13 3.3 ...................................................................................................................... 13 3.4 ...................................................................................................................... 14 3.5 .............................................................................................................................. 15 3.6 ........................................................................................................................... 15 4 ....................................................................................................................... 18 4.1 .......................................................................................................................... 18 4.2 block ......................................................................................... 19 4.3 .................................................................................................................. 20 Programming in Lua iv Copyright ® 2005, Translation Team, www.luachina.net 4.4 breakreturn............................................................................................................. 23 5 ............................................................................................................................... 24 5.1 .............................................................................................................. 25 5.2 ........................................................................................................................... 27 5.3 .......................................................................................................................... 28 6 ....................................................................................................................... 30 6.1 .................................................................................................................................. 32 6.2 ...................................................................................................................... 34 6.3 Proper Tail Calls ............................................................................... 36 7 for........................................................................................................... 40 7.1 .................................................................................................................. 40 7.2 for.................................................................................................................. 42 7.3 .............................................................................................................. 43 7.4 .............................................................................................................. 44 7.5 .................................................................................................................. 45 8 ....................................................................................................... 47 8.1 require........................................................................................................................ 49 8.2 C Packages......................................................................................................................... 50 8.3 .................................................................................................................................. 51 8.4 .............................................................................................................. 52 8.5 Tracebacks ................................................................................ 53 9 ....................................................................................................................... 56 9.1 ...................................................................................................................... 56 9.2 .................................................................................................................. 58 9.3 .......................................................................................................... 61 9.4 .............................................................................................................. 63 10 ..................................................................................................................... 68 10.1 Lua ........................................................................................... 68 10.2 ............................................................................................................ 71 tablesobjects............................................................................................................... 75 11 ..................................................................................................................... 76 11.1 ................................................................................................................................76 11.2 ................................................................................................................ 77 11.3 ................................................................................................................................78 11.4 ............................................................................................................ 78 11.5 ........................................................................................................................ 80 11.6 .................................................................................................................... 80 12 ..................................................................................................... 84 12.1 ............................................................................................................................ 86 Programming in Lua v Copyright ® 2005, Translation Team, www.luachina.net 13 Metatables and Metamethods...................................................................................... 92 13.1 Metamethods............................................................................................... 92 13.2 Metamethods............................................................................................... 95 13.3 Metamethods................................................................................................... 96 13.4 Metamethods................................................................................................... 97 14 ........................................................................................................................... 103 14.1 ...................................................................................... 103 14.2 ............................................................................................................... 104 14.3 .............................................................................................................. 106 15 Packages.................................................................................................................... 109 15.1 ...................................................................................................................... 109 15.2 Privacy...................................................................................................111 15.3 .......................................................................................................................112 15.4 ...................................................................................................................113 15.5 Other Facilities...............................................................................115 16 ....................................................................................................118 16.1 ...................................................................................................................................119 16.2 .............................................................................................................................. 121 16.3 ...................................................................................................................... 122 16.4 privacy ...................................................................................................... 125 16.5 Single-Method ................................................................................... 127 17 Weak ...................................................................................................................... 128 17.1 ...................................................................................................................... 130 17.2 .............................................................................................................. 131 17.3 .................................................................................................. 132 ......................................................................................................................... 134 18 ....................................................................................................................... 135 19 Table ...................................................................................................................... 136 19.1 ....................................................................................................................... 136 19.2 / ..................................................................................................................... 137 19.3 .............................................................................................................................. 137 20 String ..................................................................................................................... 140 20.1 .............................................................................................................. 141 20.2 .............................................................................................................................. 143 20.3 Captures........................................................................................................ 146 20.4 Tricks of the Trade............................................................................ 151 21 IO........................................................................................................................... 157 21.1 I/O................................................................................................................. 157 21.2 I/O ............................................................................................................... 160 Programming in Lua vi Copyright ® 2005, Translation Team, www.luachina.net 22 ............................................................................................................... 165 22.1 DateTime ................................................................................................................... 165 22.2 .......................................................................................................... 167 23 Debug..................................................................................................................... 169 23.1 Introspective ................................................................................................. 169 23.2 Hooks............................................................................................................................. 173 23.3 Profiles........................................................................................................................... 174 C API........................................................................................................................... 177 24 C API ................................................................................................................. 178 24.1 .......................................................................................................... 179 24.2 .............................................................................................................................. 181 24.3 C API ......................................................................................................... 186 25 ........................................................................................................... 188 25.1 .......................................................................................................................... 189 25.2 Lua................................................................................................................ 193 25.3 .......................................................................................................... 195 26 C................................................................................................................. 198 26.1 C ........................................................................................................................... 198 26.2 C ....................................................................................................................... 200 27 C..................................................................................................... 203 27.1 ...................................................................................................................... 203 27.2 .................................................................................................................. 204 27.3 C.................................................................................................... 207 28 User-Defined Types in C ........................................................................................... 212 28.1 Userdata......................................................................................................................... 212 28.2 Metatables...................................................................................................................... 215 28.3 .................................................................................................. 217 28.4 ...................................................................................................................... 219 28.5 Light Userdata ............................................................................................................... 220 29 ................................................................................................................... 222 29.1 .................................................................................................................. 222 29.2 XML ...................................................................................................................... 225 Programming in Lua 1 Copyright ® 2005, Translation Team, www.luachina.net Programming in Lua 1 Copyright ® 2005, Translation Team, www.luachina.net 0 convention 00..11 Lua Lua Lua Lua C/C++ Lua Lua C/C++ Lua Lua C Lua C Lua C Lua Lua glue language Lua C/C++ Lua CPU Lua Lua Lua Lua Lua PerlTclRubyForthPython Lua Lua Lua Lua Lua Lua C Lua Lua C/C++java fortranSmalltalkAda Lua Lua Programming in Lua 2 Copyright ® 2005, Translation Team, www.luachina.net Lua Lua Lua NextStep OS/2PlayStation II (Sony)Mac OS-9OS XBeOSMS-DOSIBM mainframesEPOCPalmOSMCF5206eLITE Evaluation BoardRISC OS Windows UnixLua ANSI (ISO) C ANSI C Lua Lua Lua Lua Lua Lua 00..22 LLuuaa Lua Lua Lua Lua C Lua CGILuaLuaOrb CORBA Lua-API Lua Lua CGILua Lua Web Lua Lua Lua Lua C Lua Lua tables , Lua table string I/O OS Programming in Lua 3 Copyright ® 2005, Translation Team, www.luachina.net Debug Lua C API C Lua Lua C/C++ 00..33 LLuuaa Lua Lua http://www.lua.org -- Lua http://lua-users.org -- http://www.inf.puc-rio.br/~roberto/book/ Lua 5.0 Lua 00..44 <1> "literal strings"'a' '[%w_]*' <2> -->: print(10) --> 10 13 + 3 --> 16 <3> <--> Lua this that this <--> that 00..55 1998 () Lua 3.12000 v4.0 2003 v5.0 upvalues C API Lua Programming in Lua 4 Copyright ® 2005, Translation Team, www.luachina.net Lua upvalues lexical scoping upvalues lexical scoping <1> Lua 5.0 <2> Lua Lua 00..66 Luiz Henrique de Figueiredo Waldemar Celes Luiz Henrique Noemi Rodriguez, Andr Carregal, Diego Nehab, Gavin Wraith Renato Cerqueira, Carlos Cassino, Toms Guisasola, Joe Myers Ed Ferguson Alexandre Nakonechnyj Rosane Teles CIP Programming in Lua 5 Copyright ® 2005, Translation Team, www.luachina.net 1 Hello World print("Hello World") hello.lua prompt> lua hello.lua ? -- defines a factorial function function fact (n) if n == 0 then return 1 else return n * fact(n-1) end end print("enter a number:") a = io.read("*number") -- read a number print(fact(a)) n n n 11..11 CChhuunnkkss Chunk Lua Chunk ; a = 1 b = a*2 -- ugly, but valid Chunk Chunk Lua MByte Chunk Lua Lua: Programming in Lua 6 Copyright ® 2005, Translation Team, www.luachina.net Lua 5.0 Copyright © 1994-2003 Tecgraf, PUC-Rio > "Hello World" Ctrl-D in Unix, Ctrl-Z in DOS/Windows OS os.exit() Lua Chunk Lua Chunk Chunk. Lua >>. Lua Chunk a x=1 b print(x) prompt> lua -la -lb Chunk a b-l require 8.1 the require function -i Lua Chunk . prompt> lua -i -la -lb Chunk a b Chunk dofile dofile . : -- file 'lib1.lua' function norm (x, y) local n2 = x^2 + y^2 return math.sqrt(n2) end function twice (x) return 2*x end > dofile("lib1.lua") -- load your library > n = norm(3.4, 1.0) > print(twice(n)) --> 7.0880180586677 -i dofile Lua Programming in Lua 7 Copyright ® 2005, Translation Team, www.luachina.net 11..22 nil. print(b) --> nil b = 10 print(b) --> 10 nil b = nil print(b) --> nil b ., nil 11..33 (letter). Lua Lua letter Lua and break do else elseif end false for function if in local nil not or repeat return then true until while Lua . :-- --[[ --]] --[[ print(10) -- no action (comment) --]] 11..44 lua [options] [script [args]] Programming in Lua 8 Copyright ® 2005, Translation Team, www.luachina.net -e Lua prompt> lua -e "print(math.sin(12))" --> -0.53657291800043 -l. -i. _PROMPT prompt> lua -i -e "_PROMPT=' lua> '" lua> Lua Lua LUA_INIT @filenameLua @Lua filename Lua arg Lua prompt> lua script a b c Lua arg 0 1 -1 prompt> lua -e "sin=math.sin" script a b arg arg[-3] = "lua" arg[-2] = "-e" arg[-1] = "sin=math.sin" arg[0] = "script" arg[1] = "a" arg[2] = "b" Programming in Lua 9 Copyright ® 2005, Translation Team, www.luachina.net 2 Lua Lua 8 nilboolean numberstringuserdatafunctionthread table type print(type("Hello world")) --> string print(type(10.4*3)) --> number print(type(print)) --> function print(type(type)) --> function print(type(true)) --> boolean print(type(nil)) --> nil print(type(type(X))) --> string print(type(a)) --> nil ('a' is not initialized) a = 10 print(type(a)) --> number a = "a string!!" print(type(a)) --> string a = print -- yes, this is valid! a(type(a)) --> function function nil 22..11 NNiill Lua nil nil nil 22..22 BBoooolleeaannss false true Lua false nil Lua 0 Programming in Lua 10 Copyright ® 2005, Translation Team, www.luachina.net 22..33 NNuummbbeerrss Lua CPU 100,000,000,000,000 Lua numbers Lua numbers Lua 4 0.4 4.57e-3 0.3e12 5e+20 22..44 SSttrriinnggss lua 8 0 Lua a = "one string" b = string.gsub(a, "one", "another") -- change string parts print(a) --> one string print(b) --> another string string Lua string Lua 1M string Lua a = "a line" b = 'another line' \Lua \a bell \b back space -- \f form feed -- \n newline -- \r carriage return -- \t horizontal tab -- \v vertical tab \\ backslash -- "\" \" double quote -- \' single quote -- Programming in Lua 11 Copyright ® 2005, Translation Team, www.luachina.net \[ left square bracket -- \] right square bracket -- > print("one line\nnext line\n\"in quotes\", 'in quotes'") one line next line "in quotes", 'in quotes' > print('a backslash inside quotes: \'\\\'') a backslash inside quotes: '\' > print("a simpler way: '\\'") a simpler way: '\' \dddddd "alo\n123\""'\97lo\10\04923"' [[...]] page = [[ An HTML Page Lua [[a text between double brackets]] ]] io.write(page) Lua string numbers string print("10" + 1) --> 11 print("10 + 1") --> 10 + 1 print("-5.3e - 10" * "2") --> -1.06e-09 print("hello" + 1) -- ERROR (cannot convert "hello") Lua string string Programming in Lua 12 Copyright ® 2005, Translation Team, www.luachina.net print(10 .. 20) --> 1020 .. Lua .. 10 == "10" string tonumber() string nil line = io.read() -- read a line n = tonumber(line) -- try to convert it to a number if n == nil then error(line .. " is not a valid number") else print(n*2) end , tostring() print(tostring(10) == "10") --> true print(10 .. "" == "10") --> true 22..55 FFuunnccttiioonnss Lua 16 Lua lua C Lua C string table I/O OS debug 22..66 UUsseerrddaattaa aanndd TThhrreeaaddss userdata C Lua userdata Lua userdata C I/O C API Programming in Lua 13 Copyright ® 2005, Translation Team, www.luachina.net 3 Lua 33..11 + - * / ^ () - () 33..22 < > <= >= == ~= false true==~= Lua nil Lua tablesuserdatafunctions a = {}; a.x = 1; a.y = 0 b = {}; b.x = 1; b.y = 0 c = a a==c but a~=b Lua "0" == 0 -- false 2 < 15 -- true "2" < "15" -- false (alphabetical order!) Lua 2 < "15" 33..33 and or not Programming in Lua 14 Copyright ® 2005, Translation Team, www.luachina.net false nil false0 true. and or true false a and b -- a false a b a or b -- a true a b print(4 and 5) --> 5 print(nil and 13) --> nil print(false and 13) --> false print(4 or 5) --> 4 print(false or 5) --> 5 x false nil x v x = x or v if not x then x = v end and or C a ? b : c Lua (a and b) or c not false true print(not nil) --> true print(not false) --> true print(not 0) --> false print(not not nil) --> false 33..44 .. -- Lua Programming in Lua 15 Copyright ® 2005, Translation Team, www.luachina.net print("Hello " .. "World") --> Hello World print(0 .. 1) --> 01 33..55 ^ not - (unary) * / + - .. < > <= >= ~= == and or ^.. a+i < b/2+1 <--> (a+i) < ((b/2)+1) 5+x^2*8 <--> 5+((x^2)*8) a < y and y <= z <--> (a < y) and (y <= z) -x^2 <--> -(x^2) x^y^z <--> x^(y^z) 33..66 Lua {}: days = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"} Lua "Sunday" days[1] 1"Monday" days[2]... print(days[4]) --> Wednesday tab = {sin(1), sin(2), sin(3), sin(4), sin(5),sin(6), sin(7), sin(8)} record a = {x=0, y=0} <--> a = {}; a.x=0; a.y=0 Programming in Lua 16 Copyright ® 2005, Translation Team, www.luachina.net table w = {x=0, y=0, label="console"} x = {sin(0), sin(1), sin(2)} w[1] = "another field" x.f = w print(w["x"]) --> 0 print(w[1]) --> another field print(x.f[1]) --> another field w.x = nil -- remove field "x" Lua table table list list = nil for line in io.lines() do list = {next=list, value=line} end l = list while l do print(l.value) l = l.next end record polyline = {color="blue", thickness=2, npoints=4, {x=0, y=0}, {x=-10, y=0}, {x=-10, y=1}, {x=0, y=1} } . print(polyline[2].x) --> -10 [expression] opnames = {["+"] = "add", ["-"] = "sub", ["*"] = "mul", ["/"] = "div"} Programming in Lua 17 Copyright ® 2005, Translation Team, www.luachina.net i = 20; s = "-" a = {[i+0] = s, [i+1] = s..s, [i+2] = s..s..s} print(opnames[s]) --> sub print(a[22]) --> --- list record : {x=0, y=0} <--> {["x"]=0, ["y"]=0} {"red", "green", "blue"} <--> {[1]="red", [2]="green", [3]="blue"} 0 days = {[0]="Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"} 0 "," a = {[1]="red", [2]="green", [3]="blue",} ","";" {x=10, y=45; "one", "two", "three"} Programming in Lua 18 Copyright ® 2005, Translation Team, www.luachina.net 4 Lua C PASCAL 44..11 a = "hello" .. "world" t.n = t.n + 1 Lua a, b = 10, 2*x <--> a=10; b=2*x Lua x, y = y, x -- swap 'x' for 'y' a[i], a[j] = a[j], a[i] -- swap 'a[i]' for 'a[i]' Lua a. > nil b. < a, b, c = 0, 1 print(a,b,c) --> 0 1 nil a, b = a+1, b+1, b+2 -- value of b+2 is ignored print(a,b) --> 1 2 a, b, c = 0 print(a,b,c) --> 0 nil nil a, b, c = 0, 0, 0 Programming in Lua 19 Copyright ® 2005, Translation Team, www.luachina.net print(a,b,c) --> 0 0 0 a, b = f() f() a b 44..22 bblloocckk local chunk x = 10 local i = 1 -- local to the chunk while i<=x do local x = i*2 -- local to the while body print(x) --> 2, 4, 6, 8, ... i = i + 1 end if i > 20 then local x -- local to the "then" body x = 20 print(x + 2) else print(x) --> 10 (the global one) end print(x) --> 10 (the global one) local i=1 chunkLua chunk i do..end c/c++{} 1. 2. . block do..end Programming in Lua 20 Copyright ® 2005, Translation Team, www.luachina.net do local a2 = 2*a local d = sqrt(b^2 - 4*a*c) x1 = (-b + d)/a2 x2 = (-b - d)/a2 end -- scope of 'a2' and 'd' ends here print(x1, x2) 44..33 Lua false nil if if conditions then then-part end; if conditions then then-part else else-part end; if conditions then then-part elseif conditions then elseif-part .. ---> elseif else else-part end; while while condition do statements; end; repeat-until Programming in Lua 21 Copyright ® 2005, Translation Team, www.luachina.net repeat statements; until conditions; for for for var=exp1,exp2,exp3 do loop-part end for exp3 step exp1 exp2 loop-part exp3 step=1 1. for i=1,f(x) do print(i) end for i=10,1,-1 do print(i) end f(x) 2. var ,. for i=1,10 do print(i) end max = i -- probably wrong! 'i' here is global -- find a value in a list local found = nil for i=1,a.n do if a[i] == value then found = i -- save value of 'i' break end end print(found) Programming in Lua 22 Copyright ® 2005, Translation Team, www.luachina.net 3. break for -- print all values of array 'a' for i,v in ipairs(a) do print(v) end for key -- print all keys of table 't' for k in pairs(t) do print(k) end for for 1. 2. days = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"} revDays = {["Sunday"] = 1, ["Monday"] = 2, ["Tuesday"] = 3, ["Wednesday"] = 4, ["Thursday"] = 5, ["Friday"] = 6, ["Saturday"] = 7} : x = "Tuesday" print(revDays[x]) --> 3 revDays = {} for i,v in ipairs(days) do revDays[v] = i end for Programming in Lua 23 Copyright ® 2005, Translation Team, www.luachina.net 44..44 bbrreeaakk rreettuurrnn break for,repeat,while return return pascal Lua break return block chunk end else until local i = 1 while a[i] do if a[i] == v then break end i = i + 1 end block return break do..end function foo () return --<< SYNTAX ERROR -- 'return' is the last statement in the next block do return end -- OK ... -- statements not reached end Programming in Lua 24 Copyright ® 2005, Translation Team, www.luachina.net 5 1.2. function func_name (arguments-list) statements-list; end; () print(8*9, 9/8) a = math.sin(3) + math.cos(10) print(os.date()) () print "Hello World" <--> print("Hello World") dofile 'a.lua' <--> dofile ('a.lua') print [[a multi-line <--> print([[a multi-line message]] message]]) f{x=10, y=20} <--> f({x=10, y=20}) type{} <--> type({}) Lua o:foo(x) o.foo(o, x) Lua Lua Lua Lua nil function f(a, b) return a or b end CALL PARAMETERS f(3) a=3, b=nil f(3, 4) a=3, b=4 f(3, 4, 5) a=3, b=4 (5 is discarded) Programming in Lua 25 Copyright ® 2005, Translation Team, www.luachina.net 55..11 Lua string.find nil s, e = string.find("hello Lua users", "Lua") print(s, e) --> 7 9 Lua return function maximum (a) local mi = 1 -- maximum index local m = a[mi] -- maximum value for i,val in ipairs(a) do if val > m then mi = i m = val end end return m, mi end print(maximum({8,10,23,12,5})) --> 23 3 Lua function foo0 () end -- returns no results function foo1 () return 'a' end -- returns 1 result function foo2 () return 'a','b' end -- returns 2 results 1. nil 2. nil x,y = foo2() -- x='a', y='b' x = foo2() -- x='a', 'b' is discarded x,y,z = 10,foo2() -- x=10, y='a', z='b' x,y = foo0() -- x=nil, y=nil x,y = foo1() -- x='a', y=nil x,y,z = foo2() -- x='a', y='b', z=nil Programming in Lua 26 Copyright ® 2005, Translation Team, www.luachina.net x,y = foo2(), 20 -- x='a', y=20 x,y = foo0(), 20, 30 -- x='nil', y=20, 30 is discarded print(foo0()) --> print(foo1()) --> a print(foo2()) --> a b print(foo2(), 1) --> a 1 print(foo2() .. "x") --> ax a = {foo0()} -- a = {} (an empty table) a = {foo1()} -- a = {'a'} a = {foo2()} -- a = {'a', 'b'} a = {foo0(), foo2(), 4} -- a[1] = nil, a[2] = 'a', a[3] = 4 return f() f() function foo (i) if i == 0 then return foo0() elseif i == 1 then return foo1() elseif i == 2 then return foo2() end end print(foo(1)) --> a print(foo(2)) --> a b print(foo(0)) -- (no results) print(foo(3)) -- (no results) print((foo0())) --> nil print((foo1())) --> a print((foo2())) --> a return unpack unpack C Lua Programming in Lua 27 Copyright ® 2005, Translation Team, www.luachina.net f(unpack(a)) unpack a f() f = string.find a = {"hello", "ll"} print(f(unpack(a))) --> 3 4 unpack C Lua function unpack(t, i) i = i or 1 if t[i] then return t[i], unpack(t, i + 1) end end 55..22 Lua C ... Lua arg arg n print printResult = "" function print(...) for i,v in ipairs(arg) do printResult = printResult .. tostring(v) .. "\t" end printResult = printResult .. "\n" end function g (a, b, ...) end CALL PARAMETERS g(3) a=3, b=nil, arg={n=0} g(3, 4) a=3, b=4, arg={n=0} g(3, 4, 5, 8) a=3, b=4, arg={5, 8; n=2} Programming in Lua 28 Copyright ® 2005, Translation Team, www.luachina.net Lua arg string.find local _, x = string.find(s, p) -- now use `x' ... select function select (n, ...) return arg[n] end print(string.find("hello hello", " hel")) --> 6 9 print(select(1, string.find("hello hello", " hel"))) --> 6 print(select(2, string.find("hello hello", " hel"))) --> 9 unpack(arg) arg Lua string.format C sprintf function fwrite(fmt, ...) return io.write(string.format(fmt, unpack(arg))) end 55..33 Lua rename -- invalid code rename(old="temp.lua", new="temp1.lua") Lua Lua rename{old="temp.lua", new="temp1.lua"} rename Programming in Lua 29 Copyright ® 2005, Translation Team, www.luachina.net function rename (arg) return os.rename(arg.old, arg.new) end GUI w = Window { x=0, y=0, width=300, height=200, title = "Lua", background="blue", border = true } function Window (options) -- check mandatory options if type(options.title) ~= "string" then error("no title") elseif type(options.width) ~= "number" then error("no width") elseif type(options.height) ~= "number" then error("no height") end -- everything else is optional _Window(options.title, options.x or 0, -- default value options.y or 0, -- default value options.width, options.height, options.background or "white", -- default options.border -- default is false (nil) ) end Programming in Lua 30 Copyright ® 2005, Translation Team, www.luachina.net 6 Lua lexical scopingfirst-class values Lua Lua Lua print a = {p = print} a.p("Hello World") --> Hello World print = math.sin -- `print' now refers to the sine function a.p(print(1)) --> 0.841470 sin = a.p -- `sin' now refers to the print function sin(10, 20) --> 10 20 Lua function foo (x) return 2*x end Lua syntactic sugar foo = function (x) return 2*x end function function (x) ... end {} table Lua C++ network = { {name = "grauna", IP = "210.26.30.34"}, {name = "arraial", IP = "210.26.30.23"}, {name = "lua", IP = "210.26.23.12"}, {name = "derain", IP = "210.26.23.20"}, } Programming in Lua 31 Copyright ® 2005, Translation Team, www.luachina.net name table.sort(network, function (a,b) return (a.name > b.name) end) Lua Lua Lua function eraseTerminal() io.write("\27[2J") end -- writes an `*' at column `x' , row `y' function mark (x,y) io.write(string.format("\27[%d;%dH*", y, x)) end -- Terminal size TermSize = {w = 80, h = 24} -- plot a function -- (assume that domain and image are in the range [-1,1]) function plot (f) eraseTerminal() for i=1,TermSize.w do local x = (i/TermSize.w)*2 - 1 local y = (f(x) + 1)/2 * TermSize.h mark(i, y) end io.read() -- wait before spoiling the screen end plot(function (x) return math.sin(x*2*math.pi) end) Lua Programming in Lua 32 Copyright ® 2005, Translation Team, www.luachina.net 66..11 names = {"Peter", "Paul", "Mary"} grades = {Mary = 10, Paul = 7, Peter = 8} table.sort(names, function (n1, n2) return grades[n1] > grades[n2] -- compare the grades end) function sortbygrade (names, grades) table.sort(names, function (n1, n2) return g r a d e s [ n 1 ] > g r a d e s [ n 2 ] -- compare the grades end) end sortbygrade sort sortbygrade grades grades external local variable upvalue upvalue Lua external local variable function newCounter() local i = 0 return function() -- anonymous function i = i + 1 return i end end c1 = newCounter() print(c1()) --> 1 print(c1()) --> 2 upvalue i i i newCounter Lua Programming in Lua 33 Copyright ® 2005, Translation Team, www.luachina.net upvalues newCounter i i c2 = newCounter() print(c2()) --> 1 print(c1()) --> 3 print(c2()) --> 2 c1c2 sort newCounter Lua GUI button button 10 function digitButton (digit) return Button{ label = digit, action = function () add_to_display(digit) end } end Button label action upvalue digit digitButton digit digit sin oldSin = math.sin math.sin = function (x) return oldSin(x*math.pi/180) end Programming in Lua 34 Copyright ® 2005, Translation Team, www.luachina.net do local oldSin = math.sin local k = math.pi/180 math.sin = function (x) return oldSin(x*k) end end sin java io open do local oldOpen = io.open io.open = function (filename, mode) if access_OK(filename, mode) then return oldOpen(filename, mode) else return nil, "access denied" end end end 66..22 Lua table Lua io.readmath.sin 1. Lib = {} Lib.foo = function (x,y) return x + y end Lib.goo = function (x,y) return x - y end 2. Lib = { foo = function (x,y) return x + y end, goo = function (x,y) return x - y end Programming in Lua 35 Copyright ® 2005, Translation Team, www.luachina.net } 3. Lua Lib = {} function Lib.foo (x,y) return x + y end function Lib.goo (x,y) return x - y end Lua chunk chunk chunk 1. local f = function (...) ... end local g = function (...) ... f() -- external local `f' is visible here ... end 2. local function f (...) ... end local fact = function (n) if n == 0 then return 1 else return n*fact(n-1) -- buggy end end Lua fact(n-1) factLua Programming in Lua 36 Copyright ® 2005, Translation Team, www.luachina.net fact local fact fact = function (n) if n == 0 then return 1 else return n*fact(n-1) end end fact fact(n-1) fact Lua local f, g -- `forward' declarations function g () ... f() ... end function f () ... g() ... end 66..33 PPrrooppeerr TTaaiill CCaallllss Lua proper tail recursion goto function f(x) return g(x) end g f g g f Programming in Lua 37 Copyright ® 2005, Translation Team, www.luachina.net Lua n function foo (n) if n > 0 then return foo(n - 1) end end function f (x) g(x) return end f g g return g(x) + 1 -- must do the addition return x or g(x) -- must adjust to 1 result return (g(x)) -- must adjust to 1 result Lua return g(...) g g Lua return x[i].foo(x[j] + a*b, i + j) goto goto(or call) function room1 () local move = io.read() if move == "south" then return room3() elseif move == "east" then return room2() Programming in Lua 38 Copyright ® 2005, Translation Team, www.luachina.net else print("invalid move") return room1() -- stay in the same room end end function room2 () local move = io.read() if move == "south" then return room4() elseif move == "west" then return room1() else print("invalid move") return room2() end end function room3 () local move = io.read() if move == "north" then return room1() elseif move == "east" then return room4() else print("invalid move") return room3() end end function room4 () print("congratilations!") end room1() goto Programming in Lua 39 Copyright ® 2005, Translation Team, www.luachina.net Programming in Lua 40 Copyright ® 2005, Translation Team, www.luachina.net 7 for for for 77..11 Lua list ipairs() function list_iter (t) local i = 0 local n = table.getn(t) return function () i = i + 1 if i <= n then return t[i] end end end list_iter (t,i,n) list list nil. while t = {10, 20, 30} iter = list_iter(t) -- creates the iterator while true do local element = iter() -- calls the iterator if element == nil then break end print(element) Programming in Lua 41 Copyright ® 2005, Translation Team, www.luachina.net end for t = {10, 20, 30} for element in list_iter(t) do print(element) end for bookkeeping iter nil for linepos function allwords() local line = io.read() -- current line local pos = 1 -- current position in the line return function () -- iterator function while line do -- repeat while there are lines local s, e = string.find(line, "%w+", pos) if s then -- found a word? pos = e + 1 -- next position is after this word return s t r i n g . s u b ( l i n e , s , e ) -- return the word else line = io.read() -- word not found; try next line pos = 1 -- restart from first position end end return nil -- no more lines: end of traversal end end string.find string.find '%w+' pos string.sub line line nil for word in allwords() do Programming in Lua 42 Copyright ® 2005, Translation Team, www.luachina.net print(word) end Lua , 77..22 ffoorr allwords for for :. for for in do end exp-list for k, v in pairs(t) do print(k, v) end k,v pair(t) for line in io.lines() do io.write(line, '\n') end nil for in for nil for Programming in Lua 43 Copyright ® 2005, Translation Team, www.luachina.net nil for var_1, ..., var_n in explist do block end do local _f, _s, _var = explist while true do local var_1, ... , var_n = _f(_s, _var) _var = var_1 if _var == nil then break end block end end f s a0 a1=f(s,a0)a2=f(s,a1) ai=nil 77..33 ipairs a = {"one", "two", "three"} for i, v in ipairs(a) do print(i, v) end ipairs Lua function iter (a, i) i = i + 1 local v = a[i] if v then return i, v end Programming in Lua 44 Copyright ® 2005, Translation Team, www.luachina.net end function ipairs (a) return iter, a, 0 end Lua ipairs(a): iter a 0 Lua iter(a,0) 1,a[1] a[1]=nil iter(a,1) 2,a[2] nil Lua pairs next function pairs (t) return next, t, nil end ipairs next for k, v in next, t do ... end exp-list Lua nexttnil 77..44 (line pairs table table table allwords ,pos) table local iterator -- to be defined later function allwords() local state = {line = io.read(), pos = 1} return iterator, state end Programming in Lua 45 Copyright ® 2005, Translation Team, www.luachina.net function iterator (state) while state.line do -- repeat while there are lines -- search for next word local s , e = s t r i n g . f i n d ( state.line, "%w+", state.pos) if s then -- found a word? -- update next position (aft er this word) state.pos = e + 1 return string.sub(state.line, s, e) else -- word not found state.line = io.read() -- try next line... state.pos = 1 -- ... from first position end end return nil -- no more lines: end loop end for 77..55 for table table Lua table '' javaC++ allwords function allwords (f) -- repeat for each line in the file for l in io.lines() do -- repeat for each word in the line for w in string.gfind(l, "%w+") do -- call the function f(w) Programming in Lua 46 Copyright ® 2005, Translation Team, www.luachina.net end end end allwords(print) 'hello' local count = 0 allwords(function (w) if w == "hello" then count = count + 1 end en ) d print(count) for local count = 0 for w in allwords() do if w == "hello" then count = count + 1 end end print(count) Lua for for break continue return Programming in Lua 47 Copyright ® 2005, Translation Team, www.luachina.net 8 Lua Lua dofile Lua dofile Lua chunk dofile loadfile dofile loadfile chunk loadfile . dofile function dofile (filename) local f = assert(loadfile(filename)) return f() end loadfile assert dofile loadfile loadfile nil loadfile dofile loadstring loadfile chunk f = loadstring("i = i + 1") f i=i+1 i = 0 f(); print(i) --> 1 f(); print(i) --> 2 loadstring Lua chunk chunk "a = 1"loadstring function () a = 1 end chunks f = loadstring("local a = 10; return a + 20") Programming in Lua 48 Copyright ® 2005, Translation Team, www.luachina.net print(f()) --> 30 loadfile loadstring nil print(loadstring("i i")) --> nil [string "i i"]:1: '=' expected near 'i' loadfile loadstring chunk Lua foo.lua -- file `foo.lua' function foo (x) print(x) end f = loadfile("foo.lua")foo chunk f() -- defines `foo' foo("ok") --> ok dostring loadstring(s)() loadstring loadstring nil attempt to call a nil value assert assert(loadstring(s))() loadstring f = loadstring("i = i + 1") f = function () i = i + 1 end , loadstring loadstring local i = 0 f = loadstring("i = i + 1") g = function () i = i + 1 end g i f iloadstring loadstring loadstring chunk return Programming in Lua 49 Copyright ® 2005, Translation Team, www.luachina.net print "enter your expression:" local l = io.read() local func = assert(loadstring("return " .. l)) print("the value of your expression is " .. func()) loadstring print "enter function to be plotted (with variable `x'):" local l = io.read() local f = assert(loadstring("return " .. l)) for i=1,20 do x = i -- global `x' (to be visible from the chunk) print(string.rep("*", f())) end 88..11 rreeqquuiirree Lua require require dofile 1. require 2. require require Lua require require require Lua ?;?.lua;c:\windows\?;/usr/local/lua/?/?.lua require "lili" lili lili.lua c:\windows\lili /usr/local/lua/lili/lili.lua require Lua LUA_PATH require LUA_PATH require "?;?.lua" Programming in Lua 50 Copyright ® 2005, Translation Team, www.luachina.net require Lua table require require require "foo" require "foo.lua" "?;?.lua" foo.lua _LOADED require require "foo"_LOADED["foo"] nil nilrequire "foo.lua" ?;?.lua;/usr/local/default.lua require require chunk _REQUIREDNAME required require "/usr/local/lua/newrequire.lua" require newrequire.lua _REQUIREDNAME required 88..22 CC PPaacckkaaggeess Lua C C Lua Lua C ANSI C C Lua C Lua Lua Lua windowsLinux FreeBSDSolaris Unix Lua print(loadlib()) bad arguments Lua loadlib : local path = "/usr/local/lua/lib/libluasocket.so" local f = loadlib(path, "luaopen_socket") loadlib Lua Lua Lua loadlib nil Programming in Lua 51 Copyright ® 2005, Translation Team, www.luachina.net local path = "/usr/local/lua/lib/libluasocket.so" -- or path = "C:\\windows\\luasocket.dll" local f = assert(loadlib(path, "luaopen_socket")) f() -- actually open the library stub stub stub LUA_PATH require C 88..33 Errare humanum est Lua Lua chunk Lua metatables error error print "enter a number:" n = io.read("*number") if not n then error("invalid input") end Lua assert print "enter a number:" n = assert(io.read("*number"), "invalid input") assert assert assert assert n = io.read() assert(tonumber(n), "invalid input: " .. n .. " is not a number") test sin table local res = math.sin(x) Programming in Lua 52 Copyright ® 2005, Translation Team, www.luachina.net if not res then -- error ... if not tonumber(x) then -- error: x is not a number ... io.open io.open nil local file, msg repeat print "enter a file name:" local name = io.read() if not name then return end -- no input file, msg = io.open(name, "r") if not file then print(msg) end until file assert file = assert(io.open(name, "r")) Lua io.open assert file = assert(io.open("no-file", "r")) --> stdin:1: no-file: No such file or directory io.open assert 88..44 Lua Lua chunk Lua Lua Lua pcall Lua Programming in Lua 53 Copyright ® 2005, Translation Team, www.luachina.net function foo () ... if unexpected_condition then error() end ... print(a[i]) -- potential error: `a' may not be a table ... end pcall if pcall(foo) then -- no errors while running `foo' ... else -- `foo' raised an error: take appropriate actions ... end pcall if pcall(function () ... end) then ... else ... pcall pcall true nil table error pcall local status, err = pcall(function () error({code=121}) end) print(err.code) --> 121 Lua error pcall 88..55 TTrraacceebbaacckkss table Lua Lua error Lua local status, err = pcall(function () a = 'a'+1 end) print(err) --> stdin:1: attempt to perform arithmetic on a string value Programming in Lua 54 Copyright ® 2005, Translation Team, www.luachina.net local status, err = pcall(function () error("my error") end) print(err) --> stdin:1: my error stdin error error function foo (str) if type(str) ~= "string" then error("string expected") end ... end foo({x=1}) Lua foo error error error function foo (str) if type(str) ~= "string" then error("string expected", 2) end ... end tracebacks pcall tracebacks pcall Lua xpcall xpcall Lua debug debug debugdebug debug.traceback, Lua traceback , debug.traceback traceback print(debug.traceback()) Programming in Lua 55 Copyright ® 2005, Translation Team, www.luachina.net Programming in Lua 56 Copyright ® 2005, Translation Team, www.luachina.net 9 coroutine 99..11 Lua table create create thread create co = coroutine.create(function () print("hi") end) print(co) --> thread: 0x8071d98 status print(coroutine.status(co)) --> suspended coroutine.resume coroutine.resume(co) --> hi "hi" print(coroutine.status(co)) --> dead yield co = coroutine.create(function () for i=1,10 do Programming in Lua 57 Copyright ® 2005, Translation Team, www.luachina.net print("co", i) coroutine.yield() end end) yield coroutine.resume(co) --> co 1 print(coroutine.status(co)) --> suspended yield ,yield yield coroutine.resume(co) --> co 2 coroutine.resume(co) --> co 3 ... coroutine.resume(co) --> co 10 coroutine.resume(co) -- prints nothing resume false print(coroutine.resume(co)) --> false cannot resume dead coroutine :resume Lua resume Lua resume-yield resume yieldresume co = coroutine.create(function (a,b,c) print("co", a,b,c) end) coroutine.resume(co, 1, 2, 3) --> co 1 2 3 resume true yield co = coroutine.create(function (a,b) coroutine.yield(a + b, a - b) end) print(coroutine.resume(co, 20, 10)) --> true 30 10 yield resume co = coroutine.create (function () Programming in Lua 58 Copyright ® 2005, Translation Team, www.luachina.net print("co", coroutine.yield()) end) coroutine.resume(co) coroutine.resume(co, 4, 5) --> co 4 5 resume co = coroutine.create(function () return 6, 7 end) print(coroutine.resume(co)) --> true 6 7 Lua However, other people use the same term semi-coroutine to denote a restricted implementation of coroutines, where a coroutine can only suspend its execution when it is not inside any auxiliary function, that is, when it has no pending calls in its control stack. yield python generator 99..22 - function producer () while true do local x = io.read() -- produce new value send(x) -- send to consumer end end Programming in Lua 59 Copyright ® 2005, Translation Team, www.luachina.net function consumer () while true do local x = receive() -- receive from producer io.write(x, "\n") -- consume new value end end receive send resume-yield yield resume resume yield send-receive .receive send function receive () local status, value = coroutine.resume(producer) return value end function send (x) coroutine.yield(x) end producer = coroutine.create( function () while true do local x = io.read() -- produce new value send(x) end end) Programming in Lua 60 Copyright ® 2005, Translation Team, www.luachina.net function receive (prod) local status, value = coroutine.resume(prod) return value end function send (x) coroutine.yield(x) end function producer () return coroutine.create(function () while true do local x = io.read() -- produce new value send(x) end end) end function filter (prod) return coroutine.create(function () local line = 1 while true do local x = receive(prod) -- get new value x = string.format("%5d %s", line, x) send(x) -- send it to consumer line = line + 1 end end) end function consumer (prod) while true do local x = receive(prod) -- get new value io.write(x, "\n") -- consume new value end end p = producer() Programming in Lua 61 Copyright ® 2005, Translation Team, www.luachina.net f = filter(p) consumer(f) consumer(filter(producer())) UNIX consumerproducer 99..33 - function permgen (a, n) if n == 0 then printResult(a) else for i=1,n do -- put i-th element as the last one a[n], a[i] = a[i], a[n] -- generate all permutations of the other elements permgen(a, n - 1) -- restore i-th element a[n], a[i] = a[i], a[n] end Programming in Lua 62 Copyright ® 2005, Translation Team, www.luachina.net end end function printResult (a) for i,v in ipairs(a) do io.write(v, " ") end io.write("\n") end permgen ({1,2,3,4}, 4) 1. printResult yield function permgen (a, n) if n == 0 then coroutine.yield(a) else ... 2. function perm (a) local n = table.getn(a) local c o = c o r o u t i n e . c r e a t e ( function ( ) p e r m g e n ( a , n ) end) return function () -- iterator local code, res = coroutine.resume(co) return res end end for for p in perm{"a", "b", "c"} do printResult(p) end --> b c a --> c b a --> c a b --> a c b --> b a c Programming in Lua 63 Copyright ® 2005, Translation Team, www.luachina.net --> a b c perm Lua resume Lua Lua coroutine.wrap create wrap wrap resume wrap resume wrap perm function perm (a) local n = table.getn(a) return coroutine.wrap(function () permgen(a, n) end) end coroutine.wrap coroutine.create resume wrap 99..44 Lua yield-resume yield bugs yield blocking operation http Diego Nehab LuaSocket LuaSocket require "luasocket" host = "www.w3.org" file = "/TR/REC-html32.html" TCP 80 http Programming in Lua 64 Copyright ® 2005, Translation Team, www.luachina.net c = assert(socket.connect(host, 80)) c:send("GET " .. file .. " HTTP/1.0\r\n\r\n") receive c:close() receive function download (host, file) local c = assert(socket.connect(host, 80)) local count = 0 -- counts number of bytes read c:send("GET " .. file .. " HTTP/1.0\r\n\r\n") while true do local s, status = receive© count = count + string.len(s) if status == "closed" then break end end c:close() print(file, count) end receive function receive (connection) return connection:receive(2^10) end Programming in Lua 65 Copyright ® 2005, Translation Team, www.luachina.net yield function receive (connection) connection:timeout(0) -- do not block local s, status = connection:receive(2^10) if status == "timeout" then coroutine.yield(connection) end return s, status end timeout(0) timeout yield false yield timeout : timeout timeout receive s threads = {} -- list of all live threads function get (host, file) -- create coroutine local co = coroutine.create(function () download(host, file) end) -- insert it in the list table.insert(threads, co) end table function dispatcher () while true do local n = table.getn(threads) if n == 0 then break end -- no more threads to run for i=1,n do local status, res = coroutine.resume(threads[i]) if not res then -- thread finished its task? table.remove(threads, i) break end Programming in Lua 66 Copyright ® 2005, Translation Team, www.luachina.net end end end W3C 4 host = "www.w3c.org" get(host, "/TR/html401/html40.txt") get(host, "/TR/2002/REC-xhtml1-20020801/xhtml1.pdf") get(host, "/TR/REC-html32.html") get(host, "/TR/2000/REC-DOM-Level-2-Core-20001113/DOM2-Core.txt") dispatcher() -- main loop 6s 15s 2 30 CPU LuaSocket select socket select function dispatcher () while true do local n = table.getn(threads) if n == 0 then break end -- no more threads to run local connections = {} for i=1,n do local status, res = coroutine.resume(threads[i]) if not res then -- thread finished its task? table.remove(threads, i) break else -- timeout table.insert(connections, res) end end Programming in Lua 67 Copyright ® 2005, Translation Team, www.luachina.net if table.getn(connections) == n then socket.select(connections) end end end timeoutreceiveyield resume timeout select CPU Programming in Lua 68 Copyright ® 2005, Translation Team, www.luachina.net 10 Lua Lua Lua Kernighan & Pike Practice of Programming Lua table C-API 1100..11 LLuuaa Lua Lua entry{ title = "Tecgraf", org = "Computer Graphics Technology Group, PUC-Rio", url = "http://www.tecgraf.puc-rio.br/", contact = "Waldemar Celes", description = [[ TeCGraf is the result of a partnership between PUC-Rio, the Pontifical Catholic University of Rio de Janeiro, and PETROBRAS, the Brazilian Oil Company. TeCGraf is Lua's birthplace, and the language has been used there since 1993. Currently, more than thirty programmers in TeCGraf use Lua regularly; they have written more than two hundred thousand lines of code, distributed among dozens of final products.]] } , Lua table entry html Projects using Lua Programming in Lua 69 Copyright ® 2005, Translation Team, www.luachina.net Here are brief descriptions of some projects around the world that use Lua.

TeCGraf Computer Graphics Technology Group, PUC-Rio

TeCGraf is the result of a partnership between ... distributed among dozens of final products.

Contact: Waldemar Celes


... entry dofile db.lua entry entry Lua 5.2 function fwrite (fmt, ...) return io.write(string.format(fmt, unpack(arg))) end BEGIN html Programming in Lua 70 Copyright ® 2005, Translation Team, www.luachina.net function BEGIN() io.write([[ Projects using Lua Here are brief descriptions of some projects around the world that use Lua. ]]) end entry a. entryentryotable function entry0 (o) N=N + 1 local title = o.title or '(no title)' fwrite('
  • %s\n', N, title) end o.title nil table title "no title" b. entry function entry1 (o) N=N + 1 local title = o.title or o.org or 'org' fwrite('
    \n

    \n') local href = '' if o.url then href = string.format(' HREF="%s"', o.url) end fwrite('%s\n', N, href, title) if o.title and o.org then fwrite('\n%s', o.org) end fwrite('\n

    \n') if o.description then fwrite('%s', string.gsub(o.description, Programming in Lua 71 Copyright ® 2005, Translation Team, www.luachina.net '\n\n\n*', '

    \n')) fwrite('

    \n') end if o.email then fwrite('Contact: %s\n', o.email, o.contact or o.email) elseif o.contact then fwrite('Contact: %s\n', o.contact) end end html END html function END() fwrite('\n') end entry entry BEGIN() N = 0 entry = entry0 fwrite('

      \n') dofile('db.lua') fwrite('
    \n') N = 0 entry = entry1 dofile('db.lua') END() 1100..22 n(n=2) Programming in Lua 72 Copyright ® 2005, Translation Team, www.luachina.net function prefix (w1, w2) return w1 .. ' ' .. w2 end NOWORD\n the more we try the more we do { ["\n \n"] = {"the"}, ["\n the"] = {"more"}, ["the more"] = {"we", "we"}, ["more we"] = {"try", "do"}, ["we try"] = {"the"}, ["try the"] = {"more"}, ["we do"] = {"\n"}, } statetab statetab function insert (index, value) if not statetab[index] then statetab[index] = {value} else table.insert(statetab[index], value) end end table.insert w1 w2 Programming in Lua 73 Copyright ® 2005, Translation Team, www.luachina.net MAXGEN=1000 w1 w2 next w1 w2 -- Markov Chain Program in Lua function allwords () local line = io.read() -- current line local pos = 1 -- current position in the line return function () -- iterator function while line do -- repeat while there are lines local s, e = string.find(line, "%w+", pos) if s then -- found a word? pos = e + 1 -- update next position return s t r i n g . s u b ( l i n e , s , e ) -- return the word else line = io.read() -- word not found; try next line pos = 1 -- restart from first position end end return nil -- no more lines: end of traversal end end function prefix (w1, w2) return w1 .. ' ' .. w2 end local statetab function insert (index, value) if not statetab[index] then statetab[index] = {n=0} end table.insert(statetab[index], value) end local N = 2 local MAXGEN = 10000 Programming in Lua 74 Copyright ® 2005, Translation Team, www.luachina.net local NOWORD = "\n" -- build table statetab = {} local w1, w2 = NOWORD, NOWORD for w in allwords() do insert(prefix(w1, w2), w) w1 = w2; w2 = w; end insert(prefix(w1, w2), NOWORD) -- generate text w1 = NOWORD; w2 = NOWORD -- reinitialize for i=1,MAXGEN do local list = statetab[prefix(w1, w2)] -- choose a random item from list local r = math.random(table.getn(list)) local nextword = list[r] if nextword == NOWORD then return end io.write(nextword, " ") w1 = w2; w2 = nextword end Programming in Lua 75 Copyright ® 2005, Translation Team, www.luachina.net tables objects Programming in Lua 76 Copyright ® 2005, Translation Team, www.luachina.net 11 table Lua arrays recordslistsqueuessets Lua table lua table C Pascal arrays listsrecord+pointer Lua table table table lua table table table arrays lists 1111..11 lua a = {} -- new array for i=1, 1000 do a[i] = 0 end a 1000 1-1000 nil 0,1 -- creates an array with indices from -5 to 5 a = {} for i=-5, 5 do a[i] = 0 end Lua 1 Lua 1 Programming in Lua 77 Copyright ® 2005, Translation Team, www.luachina.net squares = {1, 4, 9, 16, 25, 36, 49, 64, 81} 1111..22 Lua n m mt = {} -- create the matrix for i=1,N do mt[i] = {} -- create a new row for j=1,M do mt[i][j] = 0 end end Lua table table c pascal for j=1,M do for j=1,i do n m mt = {} -- create the matrix for i=1,N do for j=1,M do mt[i*M + j] = 0 end end m s t s t m[s..':'..t] s t ("a:", "b") ("a", ":b") '\0' 0 m,n Programming in Lua 78 Copyright ® 2005, Translation Team, www.luachina.net m,n x nil 10000 5 10000 10000*10000 50000 Lua table 10000 table table table 50000 nil 1111..33 Lua tables table (table) list = nil v list = {next = list, value = v} local l = list while l do print(l.value) l = l.next end Lua n 1111..44 Lua table insert remove function ListNew () return {first = 0, last = -1} Programming in Lua 79 Copyright ® 2005, Translation Team, www.luachina.net end list table List = {} function List.new () return {first = 0, last = -1} end function List.pushleft (list, value) local first = list.first - 1 list.first = first list[first] = value end function List.pushright (list, value) local last = list.last + 1 list.last = last list[last] = value end function List.popleft (list) local first = list.first if first > list.last then error("list is empty") end local value = list[first] list[first] = nil -- to allow garbage collection list.first = first + 1 return value end function List.popright (list) local last = list.last if list.first > last then error("list is empty") end local value = list[last] list[last] = nil -- to allow garbage collection list.last = last - 1 return value end Programming in Lua 80 Copyright ® 2005, Translation Team, www.luachina.net pushright popleftfirst last Lua table 1 20 16,777,216 16,777,236Lua 100 200 1111..55 C hash Lua table table nil reserved = { ["while"] = true, ["end"] = true, ["function"] = true, ["local"] = true, } for w in allwords() do if reserved[w] then -- `w' is a reserved word ... function Set (list) local set = {} for _, l in ipairs(list) do set[l] = true end return set end reserved = Set{"while", "end", "function", "local", } 1111..66 Programming in Lua 81 Copyright ® 2005, Translation Team, www.luachina.net -- WARNING: bad code ahead!! local buff = "" for line in io.lines() do buff = buff .. line .. "\n" end Lua 1 350KB Lua io.read(*all) 0.02s Lua Lua loop loop buff 50KB 20bytes Lua buff..line.."\n" 50,020 bytes buff 50KB 50KB 100 2KB Lua 5MB buff = buff .. line .. "\n" 100KB Lua 100KB Lua 200 Lua Java Java StringBuffer io.read(*all) function newStack () return {""} -- starts with an empty string Programming in Lua 82 Copyright ® 2005, Translation Team, www.luachina.net end function addString (stack, s) table.insert(stack, s) -- push 's' into the the stack for i=table.getn(stack)-1, 1, -1 do if string.len(stack[i]) > string.len(stack[i+1]) then break end stack[i] = stack[i] .. table.remove(stack) end end table.concat local s = newStack() for line in io.lines() do addString(s, line .. "\n") end s = toString(s) 350 KB 0.5s io.read("*all") 0.02s io.read("*all")io.read C Lua C table.concat table.concat table C Concat local t = {} for line in io.lines() do table.insert(t, line) end s = table.concat(t, "\n") .. "\n" io.lines concat Programming in Lua 83 Copyright ® 2005, Translation Team, www.luachina.net table.insert(t, "") s = table.concat(t, "\n") Programming in Lua 84 Copyright ® 2005, Translation Team, www.luachina.net 12 Section 10.1 10 Complete Examples Lua table Lua Lua table Lua . CSV 20 Lua CSV CSV Lua Lua Donald E. Knuth,Literate Programming,CSLI,1992 Jon Bentley,More Programming Pearls,Addison-Wesley,1990 Entry{"Donald E. Knuth", "Literate Programming", "CSLI", 1992} Entry{"Jon Bentley", "More Programming Pearls", "Addison-Wesley", 1990} Entry{...} Entry({...}) Lua Lua local count = 0 function Entry (b) count = count + 1 end Programming in Lua 85 Copyright ® 2005, Translation Team, www.luachina.net dofile("data") print("number of entries: " .. count) Entry b entry b[1] local authors = {} -- a set to collect authors function Entry (b) authors[b[1]] = true end dofile("data") for name in pairs(authors) do print(name) end Entry dofile name-value Entry{ author = "Donald E. Knuth", title = "Literate Programming", publisher = "CSLI", year = 1992 } Entry{ author = "Jon Bentley", title = "More Programming Pearls", publisher = "Addison-Wesley", year = 1990 } BibTeXLua BibTeX CSV name-value local authors = {} -- a set to collect authors function Entry (b) authors[b.author] = true end dofile("data") for name in pairs(authors) do print(name) end author Programming in Lua 86 Copyright ® 2005, Translation Team, www.luachina.net function Entry (b) if b.author then authors[b.author] = true end end Lua 2MB 1 Lua Lua chunks 1122..11 Lua varname = varname function serialize (o) if type(o) == "number" then io.write(o) else ... end : if type(o) == "string" then io.write("'", o, "'") Lua if type(o) == "string" then io.write("[[", o, "]]") " ]]..os.execute('rm *')..[[ " chunk varname = [[ ]]..os.execute('rm *')..[[ ]] load string "%q" function serialize (o) Programming in Lua 87 Copyright ® 2005, Translation Team, www.luachina.net if type(o) == "number" then io.write(o) elseif type(o) == "string" then io.write(string.format("%q", o)) else ... end 1122..11..11 ttaabbllee function serialize (o) if type(o) == "number" then io.write(o) elseif type(o) == "string" then io.write(string.format("%q", o)) elseif type(o) == "table" then io.write("{\n") for k,v in pairs(o) do io.write(" ", k, " = ") serialize(v) io.write(",\n") end io.write("}\n") else error("cannot serialize a " .. type(o)) end end Lua io.write(" ", k, " = ") Programming in Lua 88 Copyright ® 2005, Translation Team, www.luachina.net io.write(" [") serialize(k) io.write(") = ") -- result of serialize{a=12, b='Lua', key='another "one"'} -- { a = 12, b = "Lua", key = "another \"one\"", } -- { ["a"] = 12, ["b"] = "Lua", ["key"] = "another \"one\"", } 1122..11..22 ttaabbllee table table table table table table function basicSerialize (o) if type(o) == "number" then return tostring(o) else -- assume it is a string return string.format("%q", o) end Programming in Lua 89 Copyright ® 2005, Translation Team, www.luachina.net end saved table function save (name, value, saved) saved = saved or {} -- initial value io.write(name, " = ") if t y p e ( v a l u e ) = = "number" or t y p e ( v a l u e ) = = "string" then io.write(basicSerialize(value), "\n") elseif type(value) == "table" then if saved[value] then -- value already saved? -- use its previous name io.write(saved[value], "\n") else saved[value] = name -- save name for next time io.write("{}\n") -- create a new table for k,v in pairs(value) do -- save its fields local f i e l d n a m e = s t r i n g . f o r m a t ( "%s[%s]", name, basicSerialize(k)) save(fieldname, v, saved) end end else error("cannot save a " .. type(value)) end end table a = {x=1, y=2; {3,4,5}} a[2] = a -- cycle a.z = a[1] -- shared sub-table save('a', a) a = {} a[1] = {} a[1][1] = 3 a[1][2] = 4 a[1][3] = 5 Programming in Lua 90 Copyright ® 2005, Translation Team, www.luachina.net a[2] = a a["y"] = 2 a["x"] = 1 a["z"] = a[1] table table saved save a = {{"one", "two"}, 3} b = {k = a[1]} save('a', a) save('b', b) a = {} a[1] = {} a[1][1] = "one" a[1][2] = "two" a[2] = 3 b = {} b["k"] = {} b["k"][1] = "one" b["k"][2] = "two" saved save local t = {} save('a', a, t) save('b', b, t) a = {} a[1] = {} a[1][1] = "one" a[1][2] = "two" a[2] = 3 b = {} b["k"] = a[1] Programming in Lua 91 Copyright ® 2005, Translation Team, www.luachina.net Lua chunk local Lua Programming in Lua 92 Copyright ® 2005, Translation Team, www.luachina.net 13 Metatables and Metamethods Lua table key-value key value key-value table Metatables table Metatables Lua table a+b Lua Metatable Metatable __add __add Metamethod Lua Metatable userdata Metatable Lua metatable t = {} print(getmetatable(t)) --> nil setmetatable metatable t1 = {} setmetatable(t, t1) assert(getmetatable(t) == t1) metatable metatable metatable 1133..11 MMeettaammeetthhooddss metamethods table like Set = {} function Set.new (t) local set = {} for _, l in ipairs(t) do set[l] = true end return set Programming in Lua 93 Copyright ® 2005, Translation Team, www.luachina.net end function Set.union (a,b) local res = Set.new{} for k in pairs(a) do res[k] = true end for k in pairs(b) do res[k] = true end return res end function Set.intersection (a,b) local res = Set.new{} for k in pairs(a) do res[k] = b[k] end return res end function Set.tostring (set) local s = "{" local sep = "" for e in pairs(set) do s = s .. sep .. e sep = ", " end return s .. "}" end function Set.print (s) print(Set.tostring(s)) end (+) metatable metatable metatable set Set.mt = {} -- metatable for sets set.new metatable function Set.new (t) -- 2nd version Programming in Lua 94 Copyright ® 2005, Translation Team, www.luachina.net local set = {} setmetatable(set, Set.mt) for _, l in ipairs(t) do set[l] = true end return set end set.new metatable s1 = Set.new{10, 20, 30, 50} s2 = Set.new{30, 1} print(getmetatable(s1)) --> table: 00672B60 print(getmetatable(s2)) --> table: 00672B60 metatable __add Set.mt.__add = Set.union Lua metamethod s3 = s1 + s2 Set.print(s3) --> {1, 10, 20, 30, 50} Set.mt.__mul = Set.intersection Set.print((s1 + s2)*s1) --> {10, 20, 30, 50} metatable __add,__mul __sub(),__div(),__unm(),__pow()__concat metatable s = Set.new{1,2,3} s = s + 8 Lua metamethod __add metatableLua metamethod __add metatableLua metamethod Lua s=s+8 Set.union bad argument #1 to `pairs' (table expected, got number) Programming in Lua 95 Copyright ® 2005, Translation Team, www.luachina.net function Set.union (a,b) if getmetatable(a) ~= Set.mt or getmetatable(b) ~= Set.mt then error("attempt to `add' a set with a non-set value", 2) end ... -- same as before 1133..22 MMeettaammeetthhooddss Metatables metamethods__eq__lt__le metamethod Lua a ~= b not (a == b)a > b b < aa >= b b <= a Lua 4.0 a <= b not (b < a) partial order Not a Number NaN IEEE 754 NaN 0/0 NaN false NaN <= x falsex < NaN false a <= b not (b < a) <=a <= b a b a <= b b < a false __le __lt Set.mt.__le = function (a,b) -- set containment for k in pairs(a) do if not b[k] then return false end end return true end Set.mt.__lt = function (a,b) return a <= b and not (b <= a) end Set.mt.__eq = function (a,b) return a <= b and b <= a end Programming in Lua 96 Copyright ® 2005, Translation Team, www.luachina.net s1 = Set.new{2, 4} s2 = Set.new{4, 10, 2} print(s1 <= s2) --> true print(s1 < s2) --> true print(s1 >= s1) --> true print(s1 > s1) --> false print(s1 == s2 * s1) --> true metamethods metamethods Lua Lua . metamethods Lua metamethod false metamethod Lua Lua metamethod Lua metamethod 1133..33 MMeettaammeetthhooddss metatables metamethods Lua metatables metamethodsmetatable tostring tostring table print({}) --> table: 0x8062ac0 print tostring tostring __tostring metatable tostring metatable __tostring Set.mt.__tostring = Set.tostring print print tostring tostring Set.tostring s1 = Set.new{10, 4, 5} print(s1) --> {4, 5, 10} setmetatable/getmetatable metafield Programming in Lua 97 Copyright ® 2005, Translation Team, www.luachina.net metatables metatables metatable __metatable getmetatable setmetatable Set.mt.__metatable = "not your business" s1 = Set.new{} print(getmetatable(s1)) --> not your business setmetatable(s1, {}) stdin:1: cannot change protected metatable 1133..44 MMeettaammeetthhooddss metamethods Lua tables 1133..44..11 TThhee ____iinnddeexx MMeettaammeetthhoodd nil lua __index metamethod nil__index metamethod metatable -- create a namespace Window = {} -- create the prototype with default values Window.prototype = {x=0, y=0, width=100, height=100, } -- create a metatable Window.mt = {} -- declare the constructor function function Window.new (o) setmetatable(o, Window.mt) return o end Programming in Lua 98 Copyright ® 2005, Translation Team, www.luachina.net __index metamethod Window.mt.__index = function (table, key) return Window.prototype[key] end w = Window.new{x=10, y=20} print(w.width) --> 100 Lua w width metatable __index Lua wthe table width__index metamethodmetamethod prototype __index metamethod Lua __index metamethod Lua table Lua Window.mt.__index = Window.prototype Lua metatable __index window.prototype Lua Window.prototype["width"] __index metamethod 16 __index metamethod rawget Rawget(t,i) raw access the overhead of a function call kills any gain you could have 1133..44..22 TThhee ____nneewwiinnddeexx MMeettaammeetthhoodd __newindex metamethod __index __newindex metamethod __index metamethod raw metamethod rawset(t,k,v) metamethod t k v__index __newindex metamethods Programming in Lua 99 Copyright ® 2005, Translation Team, www.luachina.net 1133..44..33 nil metatables function setDefault (t, d) local mt = {__index = function () return d end} setmetatable(t, mt) end tab = {x=10, y=20} print(tab.x, tab.z) --> 10 nil setDefault(tab, 0) print(tab.x, tab.z) --> 10 0 __index metamethod 0setDefault metatable metatable d metatable metatable "___" local mt = {__index = function (t) return t.___ end} function setDefault (t, d) t.___ = d setmetatable(t, mt) end local key = {} -- unique key local mt = {__index = function (t) return t[key] end} function setDefault (t, d) t[key] = d setmetatable(t, mt) end weak table 17 memoize Programming in Lua 100 Copyright ® 2005, Translation Team, www.luachina.net metatables weak tables 17 1133..44..44 __index __newindex __index __newindex metamethods t t = {} -- original table (created somewhere) -- keep a private access to original table local _t = t -- create proxy t = {} -- create metatable local mt = { __index = function (t,k) print("*access to element " .. tostring(k)) return _t[k] -- access the original table end, __newindex = function (t,k,v) print("*update of element " .. tostring(k) .. " to " .. tostring(v)) _t[k] = v -- update original table end } setmetatable(t, mt) t > t[2] = 'hello' *update of element 2 to hello > print(t[2]) *access to element 2 hello Pairs proxy Programming in Lua 101 Copyright ® 2005, Translation Team, www.luachina.net metatable proxy proxy metatable proxy proxy key -- create private index local index = {} -- create metatable local mt = { __index = function (t,k) print("*access to element " .. tostring(k)) return t[index][k] -- access the original table end __newindex = function (t,k,v) print("*update of element " .. tostring(k) .. " to " .. tostring(v)) t[index][k] = v -- update original table end } function track (t) local proxy = {} proxy[index] = t setmetatable(proxy, mt) return proxy end t t=track(t) 1133..44..55 __index metamethod metatable__index function readOnly (t) Programming in Lua 102 Copyright ® 2005, Translation Team, www.luachina.net local proxy = {} local mt = { -- create metatable __index = t, __newindex = function (t,k,v) error("attempt to update a read-only table", 2) end } setmetatable(proxy, mt) return proxy end error 2 update days = readOnly{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"} print(days[1]) --> Sunday days[2] = "Noday" stdin:1: attempt to update a read-only table Programming in Lua 103 Copyright ® 2005, Translation Team, www.luachina.net 14 Lua environment Lua environment global Lua () Lua _G _G._G _G for n in pairs(_G) do print(n) end 1144..11 meta-programming loadstring("value = " .. varname)() or value = loadstring("return " .. varname)() varname x"return x" "value = x" chunk value = _G[varname] _G[varname] = value _G["a"] = _G["var1"] a = var1 "io.read" or "a.b.c.d" _G function getfield (f) local v = _G -- start with the table of globals Programming in Lua 104 Copyright ® 2005, Translation Team, www.luachina.net for w in string.gfind(f, "[%w_]+") do v = v[w] end return v end string gfind f a.b.c.d.e = v local temp = a.b.c.d temp.e = v setfield function setfield (f, v) local t = _G -- start with the table of globals for w, d in string.gfind(f, "([%w_]+)(.?)") do if d == "." then -- not last field? t[w] = t[w] or {} -- create table if absent t = t[w] -- get the table else -- last field t[w] = v -- do the assignment end end end w d 20 setfield("t.x.y", 10) t t.x t.x.y 10 print(t.x.y) --> 10 print(getfield("t.x.y")) --> 10 1144..22 Programming in Lua 105 Copyright ® 2005, Translation Team, www.luachina.net bug Lua metatables setmetatable(_G, { __newindex = function (_, n) error("attempt to write to undeclared variable "..n, 2) end, __index = function (_, n) error("attempt to read undeclared variable "..n, 2) end, }) > a = 1 stdin:1: attempt to write to undeclared variable a rawset metamethod function declare (name, initval) rawset(_G, name, initval or false) end or false nil before installing the access control > a = 1 stdin:1: attempt to write to undeclared variable a > declare "a" > a = 1 -- OK nil nil rawget metamethod if rawget(_G, var) == nil then -- 'var' is undeclared ... end nil Programming in Lua 106 Copyright ® 2005, Translation Team, www.luachina.net metamethod local declaredNames = {} function declare (name, initval) rawset(_G, name, initval) declaredNames[name] = true end setmetatable(_G, { __newindex = function (t, n, v) if not declaredNames[n] then error("attempt to write to undeclared var. "..n, 2) else rawset(t, n, v) -- do the actual set end end, __index = function (_, n) if not declaredNames[n] then error("attempt to read undeclared var. "..n, 2) else return nil end end, }) metamethods nil 1144..33 metatable Lua 5.0 Section 15.4 setfenv Setfenv 1 2 Programming in Lua 107 Copyright ® 2005, Translation Team, www.luachina.net setfenv a = 1 -- create a global variable -- change current environment to a new empty table setfenv(1, {}) print(a) stdin:5: attempt to call global `print' (a nil value) chunk setfenv _G populate a = 1 -- create a global variable -- change current environment setfenv(1, {_G = _G}) _G.print(a) --> nil _G.print(_G.a) --> 1 "global" _G print (populate) a = 1 local newgt = {} -- create new environment setmetatable(newgt, {__index = _G}) setfenv(1, newgt) -- set it print(a) --> 1 print a _G -- continuing previous code a = 10 print(a) --> 10 print(_G.a) --> 1 _G.a = 20 print(_G.a) --> 20 chunk chunk Programming in Lua 108 Copyright ® 2005, Translation Team, www.luachina.net Programming in Lua 109 Copyright ® 2005, Translation Team, www.luachina.net 15 Packages Modula modulesJava Perl packagesC++ namespaces package Lua packages package packages packages packages (first-class values) Lua pachages package 1155..11 r i complex = {} function complex.new (r, i) return {r=r, i=i} end -- defines a constant `i' complex.i = complex.new(0, 1) function complex.add (c1, c2) return complex.new(c1.r + c2.r, c1.i + c2.i) end function complex.sub (c1, c2) return complex.new(c1.r - c2.r, c1.i - c2.i) end Programming in Lua 110 Copyright ® 2005, Translation Team, www.luachina.net function complex.mul (c1, c2) return complex.new(c1.r*c2.r - c1.i*c2.i, c1.r*c2.i + c1.i*c2.r) end function complex.inv (c) local n = c.r^2 + c.i^2 return complex.new(c.r/n, -c.i/n) end return complex coplex c = complex.add(complex.i, complex.new(10, 20)) local P = {} complex = P -- package name P.i = {r=0, i=1} function P.new (r, i) return {r=r, i=i} end function P.add (c1, c2) return P.new(c1.r + c2.r, c1.i + c2.i) end ... return complex return package complex package package Programming in Lua 111 Copyright ® 2005, Translation Team, www.luachina.net 1155..22 PPrriivvaaccyy package package package package Lua local P = {} complex = P local function checkComplex (c) if not ((type(c) == "table") and tonumber(c.r) and tonumber(c.i)) then error("bad complex number", 3) end end function P.add (c1, c2) checkComplex(c1); checkComplex(c2); return P.new(c1.r + c2.r, c1.i + c2.i) end ... return P package Package entity privacy package package P. () package complex package local function checkComplex (c) if not ((type(c) == "table") and tonumber(c.r) and tonumber(c.i)) then error("bad complex number", 3) end Programming in Lua 112 Copyright ® 2005, Translation Team, www.luachina.net end local function new (r, i) return {r=r, i=i} end local function add (c1, c2) checkComplex(c1); checkComplex(c2); return new(c1.r + c2.r, c1.i + c2.i) end ... complex = { new = new, add = add, sub = sub, mul = mul, div = div, } package package 1155..33 package package package complex.lua require complex package require package package package require packages package .luaLua "/usr/local/lualibs/?.lua" package complex.lua packagepackage package Lua _REQUIREDNAME require Programming in Lua 113 Copyright ® 2005, Translation Team, www.luachina.net package local P = {} -- package if _REQUIREDNAME == nil then complex = P else _G[_REQUIREDNAME] = P end if require package _REQUIREDNAME package complex package cpx.lua require cpx package cpx cpx_v1.lua require cpx_v1 package cpx_v1 1155..44 package local Metamethods packagepackage package chunk package package package package package local P = {} complex = P setfenv(1, P) add, complex.add: function add (c1, c2) return new(c1.r + c2.r, c1.i + c2.i) end package add new complex.new package package local Programming in Lua 114 Copyright ® 2005, Translation Team, www.luachina.net package local P = {} -- package if _REQUIREDNAME == nil then complex = P else _G[_REQUIREDNAME] = P end setfenv(1, P) packages P local P = {} -- package setmetatable(P, {__index = _G}) setfenv(1, P) setfenv setmetatable package package package sin complex.math.sin(x) Perl's package packages local P = {} pack = P local _G = _G setfenv(1, P) _G. metamethod packages local local P = {} pack = P -- Import Section: -- declare everything this package needs from outside Programming in Lua 115 Copyright ® 2005, Translation Team, www.luachina.net local sqrt = math.sqrt local io = io -- no more external access after this point setfenv(1, P) package 1155..55 OOtthheerr FFaacciilliittiieess packages Lua package chunk package function complex.div (c1, c2) return complex.mul(c1, complex.inv(c2)) end packages package do local package local add, i = complex.add, complex.i c1 = add(complex.new(10, 20), i) packagepackage local C = complex c1 = C.add(C.new(10, 20), C.i) package package function openpackage (ns) for n,v in pairs(ns) do _G[n] = v end end openpackage(complex) c1 = mul(new(10, 20), i) Programming in Lua 116 Copyright ® 2005, Translation Team, www.luachina.net package function openpackage (ns) for n,v in pairs(ns) do if _G[n] ~= nil then error("name clash: " . . n . . " is already defined") end _G[n] = v end end packages packages packages package package package package __index metamethod __index metamethod __index ( ) function pack1.foo () ... end function pack1.goo () ... end package package package local location = { foo = "/usr/local/lua/lib/pack1_1.lua", goo = "/usr/local/lua/lib/pack1_1.lua", foo1 = "/usr/local/lua/lib/pack1_2.lua", goo1 = "/usr/local/lua/lib/pack1_3.lua", } package metamethod pack1 = {} Programming in Lua 117 Copyright ® 2005, Translation Team, www.luachina.net setmetatable(pack1, {__index = function (t, funcname) local file = location[funcname] if not file then error("package pack1 does not define " .. funcname) end assert(loadfile(file))() -- load and run definition return t[funcname] -- return the function end}) return pack1 package pack1.foo()__index metamethod Lua C metamethod loadlib metamethod packages. Programming in Lua 118 Copyright ® 2005, Translation Team, www.luachina.net 16 Lua table Account = {balance = 0} function Account.withdraw (v) Account.balance = Account.balance - v end Account withdraw Account.withdraw(100.00) Account Account Account withdraw a = Account; Account = nil a.withdraw(100.00) -- ERROR! self this function Account.withdraw (self, v) self.balance = self.balance - v end a1 = Account; Account = nil ... a1.withdraw(a1, 100.00) -- OK self a2 = {balance=0, withdraw = Account.withdraw} Programming in Lua 119 Copyright ® 2005, Translation Team, www.luachina.net ... a2.withdraw(a2, 260.00) self OO Lua function Account:withdraw (v) self.balance = self.balance - v end a:withdraw(100.00) dot Account = { balance=0, withdraw = function (self, v) self.balance = self.balance - v end } function Account:deposit (v) self.balance = self.balance + v end Account.deposit(Account, 200.00) Account:withdraw(100.00) class accounts Account 1166..11 Lua shapeprototype Self NewtonScript Lua Programming in Lua 120 Copyright ® 2005, Translation Team, www.luachina.net prototype prototype class instance prototype Lua prototypes. a b b a prototype setmetatable(a, {__index = b}) a b b a Account __index metamethod Account account metatable Account metatable function Account:new (o) o = o or {} -- create object if user does not provide one setmetatable(o, self) self.__index = self return o end Account:new self Account Account self self a = Account:new{balance = 0} a:deposit(100.00) a a Account metatable Account:new self Account a:deposit(100.00) a.deposit(a,100.00)Lua a deposit metatable __index getmetatable(a).__index.deposit(a, 100.00) a metatable AccountAccount.__index Account new self.__index = self Account.deposit(a, 100.00) Lua a self deposit Account deposit Account Programming in Lua 121 Copyright ® 2005, Translation Team, www.luachina.net Account balance 0 balance b = Account:new() print(b.balance) --> 0 b deposit b.balance = b.balance + v self b b.balance 0 b.balance b.balance index metamethod b balance 1166..22 Lua Account Account = {balance = 0} function Account:new (o) o = o or {} setmetatable(o, self) self.__index = self return o end function Account:deposit (v) self.balance = self.balance + v end function Account:withdraw (v) if v > self.balance then error"insufficient funds" end self.balance = self.balance - v end SpecialAccount SpecialAccount = Account:new() Programming in Lua 122 Copyright ® 2005, Translation Team, www.luachina.net SpecialAccount Account s = SpecialAccount:new{limit=1000.00} SpecialAccount Account new new self SpecialAccounts metatable SpecialAccount__index SpecialAccount s SpecialAccount Account s:deposit(100.00) Lua s deposit SpecialAccount SpecialAccount Account SpecialAccount function SpecialAccount:withdraw (v) if v - self.balance >= self:getLimit() then error"insufficient funds" end self.balance = self.balance - v end function SpecialAccount:getLimit () return self.limit or 0 end s:withdraw(200.00)Lua Account SpecialAccount withdraw s.limit 1000.00 s s balance Lua s 10% function s:getLimit () return self.balance * 0.10 end s:withdraw(200.00) SpecialAccount withdraw self:getLimit 1166..33 Lua (primitive) Lua index metamethod Lua Programming in Lua 123 Copyright ® 2005, Translation Team, www.luachina.net __index metatable __index Lua Lua __index __index createClass metatable __index metamethod metatable metatable metatable metatable -- look up for `k' in list of tables 'plist' local function search (k, plist) for i=1, table.getn(plist) do local v = plist[i][k] -- try 'i'-th superclass if v then return v end end end function createClass (...) local c = {} -- new class -- class will search for each method in the list of its -- parents (`arg' is the list of parents) setmetatable(c, {__index = function (t, k) return search(k, arg) end}) -- prepare `c' to be the metatable of its instances c.__index = c -- define a new constructor for this new class function c:new (o) o = o or {} setmetatable(o, c) return o Programming in Lua 124 Copyright ® 2005, Translation Team, www.luachina.net end -- return new class return c end createClass Account NamedNamed setname and getname Named = {} function Named:getname () return self.name end function Named:setname (n) self.name = n end createClass NamedAccount = createClass(Account, Named) account = NamedAccount:new{name = "Paul"} print(account:getname()) --> Paul Lua account getname account metatable __index NamedAccountNamedAccount getname Lua NamedAccount metatable __index Lua Account getname Named index ... setmetatable(c, {__index = function (t, k) local v = search(k, arg) t[k] = v -- save for next access return v end}) ... Programming in Lua 125 Copyright ® 2005, Translation Team, www.luachina.net 1166..44 pprriivvaaccyy C++ Java Smalltalk Simula Lua tables Lua Lua Lua Lua If you do not want to access something inside an object, just do not do it. Lua meta-mechanisms Lua Lua function newAccount (initialBalance) local self = {balance = initialBalance} local withdraw = function (v) self.balance = self.balance - v end local deposit = function (v) self.balance = self.balance + v end local getBalance = function () return self.balance end return { Programming in Lua 126 Copyright ® 2005, Translation Team, www.luachina.net withdraw = withdraw, deposit = deposit, getBalance = getBalance } end self self self acc1 = newAccount(100.00) acc1.withdraw(40.00) print(acc1.getBalance()) --> 60 self newAccount newAccount 10% function newAccount (initialBalance) local self = { balance = initialBalance, LIM = 10000.00, } local extra = function () if self.balance > self.LIM then return self.balance*0.10 else return 0 end end local getBalance = function () return self.balance + self.extra() end ... Programming in Lua 127 Copyright ® 2005, Translation Team, www.luachina.net extra 1166..55 SSiinnggllee--MMeetthhoodd OO 7.1 single-method single-method single-method dispatch function newObject (value) return function (action, v) if action == "get" then return value elseif action == "set" then value = v else error("invalid action") end end end d = newObject(0) print(d("get")) --> 0 d("set", 10) print(d("get")) --> 10 d("set",10) d:set(10) Tcl/Tk widgets Tk a widget command Programming in Lua 128 Copyright ® 2005, Translation Team, www.luachina.net 17 Weak Lua Lua BUG dangling pointers Lua Lua Lua Lua nil Lua Lua Weak Lua weak Lua weak weak Lua weak tables weak weak tables weak table weak tables Lua keys values keys values keys values weak tables keys vaules weak weak tablesweak keys tablesweak values tables weak tables keys values weak table keys vaule entry table Programming in Lua 129 Copyright ® 2005, Translation Team, www.luachina.net weak metatable __mode k table keys weak v table vaules weak weak tables a = {} b = {} setmetatable(a, b) b.__mode = \"k\" -- now 'a' has weak keys key = {} -- creates first key a[key] = 1 key = {} -- creates second key a[key] = 2 collectgarbage() -- forces a garbage collection cycle for k, v in pairs(a) do print(v) end --> 2 key={} key key table key key weak table table key table key vaule weak table tables Lua {} table functionend Lua a.. bab Lua weak tables vaule Programming in Lua 130 Copyright ® 2005, Translation Team, www.luachina.net 1177..11 Lua loadstring loadstring loadstring closeconnection table loadstring loadstring table loadstring table local results = {} function mem_loadstring (s) if results[s] then -- result available? return results[s] -- reuse it else local res = loadstring(s) -- compute new result results[s] = res -- save for later reuse return res end end table weak table weak local results = {} setmetatable(results, {__mode = \"v\"}) -- make values weak function mem_loadstring (s) ... -- as before table table weak setmetatable(results, {__mode = \"kv\"}) tables Programming in Lua 131 Copyright ® 2005, Translation Team, www.luachina.net function createRGB (r, g, b) return {red = r, green = g, blue = b} end table key local results = {} setmetatable(results, {__mode = \"v\"}) -- make values weak function createRGB (r, g, b) local key = r .. \"-\" .. g .. \"-\" .. b if results[key] then return results[key] else local newcolor = {red = r, green = g, blue = b} results[key] = newcolor return newcolor end end table tales table 1177..22 weak tables tables key table key table tables table table tables key vaule table Lua key table table Programming in Lua 132 Copyright ® 2005, Translation Team, www.luachina.net table keyLua key table weak table weak keysweak keys key table weak vaules Lua table Lua weak table value 1177..33 13.4.3 nil weak tables weak table vaules table local defaults = {} setmetatable(defaults, {__mode = \"k\"}) local mt = {__index = function (t) return defaults[t] end} function setDefault (t, d) defaults[t] = d setmetatable(t, mt) end weak keys tables metatables metatable local metas = {} setmetatable(metas, {__mode = \"v\"}) function setDefault (t, d) local mt = metas[d] if mt == nil then Programming in Lua 133 Copyright ® 2005, Translation Team, www.luachina.net mt = {__index = function () return d end} metas[d] = mt -- memoize end setmetatable(t, mt) end weak vaules metatables tables metas tables tabels vaules Programming in Lua 134 Copyright ® 2005, Translation Team, www.luachina.net Programming in Lua 135 Copyright ® 2005, Translation Team, www.luachina.net 18 sin, cos, tan, asin, acos, etc. exp, log, log10floor, ceil maxmin pi ^ Lua4.0 deg rad degree local sin, asin, ... = math.sin, math.asin, ... local deg, rad = math.deg, math.rad math.sin = function (x) return sin(rad(x)) end math.asin = function (x) return deg(asin(x)) end ... math.random [0,1). n 1 <= x <= n x. a b, a <= x <= b x. randomseed math.randomseed(os.time()) os.time Programming in Lua 136 Copyright ® 2005, Translation Team, www.luachina.net 19 Table table table Lua array list array 1199..11 Lua array nil array nil array array nil array Table array getn array setn array table table weaktable table table table.setn(t, n) t n weaktable table.getn(t) table t t n setn getn Getn array array nil array table.getn(t) print(table.getn{10,2,4}) --> 3 print(table.getn{10,2,nil}) --> 2 print(table.getn{10,2,nil; n=3}) --> 3 print(table.getn{n=1000}) --> 1000 a = {} print(table.getn(a)) --> 0 table.setn(a, 10000) print(table.getn(a)) --> 10000 a = {n=10} print(table.getn(a)) --> 10 table.setn(a, 10000) print(table.getn(a)) --> 10000 Programming in Lua 137 Copyright ® 2005, Translation Team, www.luachina.net setn getn array n Lua arg setn array setn getn array n table sortconcatinsert setn n lua getn setn 1199..22 // table list table.insert array insert array using setn a {10,20,30} table.insert(a,1,15)a {15,10,20,30} insert array array a = {} for line in io.lines() do table.insert(a, line) end print(table.getn(a)) --> (number of lines read) table.remove array a={} push table.insert(a,x) pop table.remove(a) table.insert(a,1,x) table.remove(a,1) table C () 1199..33 table.sort array array truesort Programming in Lua 138 Copyright ® 2005, Translation Team, www.luachina.net array array lines = { luaH_set = 10, luaH_get = 24, luaH_present = 48, } pairs key a = {} for n in pairs(lines) do table.insert(a, n) end table.sort(a) for i,n in ipairs(a) do print(n) end Lua ipairs pairs key 12 key f keys key value function pairsByKeys (t, f) local a = {} for n in pairs(t) do table.insert(a, n) end table.sort(a, f) local i = 0 -- iterator variable local iter = function () -- iterator function i = i + 1 if a[i] == nil then return nil else return a[i], t[a[i]] end end return iter end Programming in Lua 139 Copyright ® 2005, Translation Team, www.luachina.net for name, line in pairsByKeys(lines) do print(name, line) end luaH_get 24 luaH_present 48 luaH_set 10 Programming in Lua 140 Copyright ® 2005, Translation Team, www.luachina.net 20 String Lua Lua string String string.len(s) s string.rep(s, n) n s string.rep("a", 2^20) 1M bytes string.lower(s) s string.upper table.sort(a, function (a, b) return string.lower(a) < string.lower(b) end) string.upper string.lower European Latin-1 string.upper("a??o") --> "A??O". string.sub(s,i,j) s i j Lua 1 -1 -2 string.sub(s, 1, j) s j string.sub(s, j, -1) j 3 -1 string.sub(s, j)string.sub(s, 2, -2) s = "[in brackets]" print(string.sub(s, 2, -2)) --> in brackets Lua String.sub Lua string.sub(s, 2, -2) s s = string.sub(s, 2, -2) string.char string.byte string.char 0 string.byte(s, i) s i Programming in Lua 141 Copyright ® 2005, Translation Team, www.luachina.net i=1 ASCII print(string.char(97)) --> a i = 99; print(string.char(i, i+1, i+2)) --> cde print(string.byte("abc")) --> 97 print(string.byte("abc", 2)) --> 98 print(string.byte("abc", -1)) --> 99 string.format C printf C printf 'd''x''o' 'f''s''%' print(string.format("pi = %.4f", PI)) --> pi = 3.1416 d = 5; m = 11; y = 1990 print(string.format("%02d/%02d/%04d", d, m, y)) --> 05/11/1990 tag, title = "h1", "a title" print(string.format("<%s>%s", tag, title, tag)) -->

    a title

    %.4f 4 %02d 0%2d 0 lua C Lua C printf 2200..11 string string.findstring.gsub and string.gfind LuaPOSIX2regexp POSIX regexp 4000 LuaLua 500 POSIX LuaPOSIX 2 POSIXunixregexpunixPOSIXregexp Programming in Lua 142 Copyright ® 2005, Translation Team, www.luachina.net string.find subject string nil. 'hello'"hello" s = "hello world" i, j = string.find(s, "hello") print(i, j) --> 1 5 print(string.sub(s, i, j)) --> hello print(string.find(s, "world")) --> 7 11 i, j = string.find(s, "l") print(i, j) --> 3 3 print(string.find(s, "lll")) --> nil string.sub string.find string.find local t = {} -- table to store the indices local i = 0 while true do i = string.find(s, "\n", i+1) -- find 'next' newline if i == nil then break end table.insert(t, i) end string.gfind string.gsub s = string.gsub("Lua is cute", "cute", "great") print(s) --> Lua is great s = string.gsub("all lii", "l", "x") print(s) --> axx xii s = string.gsub("Lua is great", "perl", "tcl") print(s) --> Lua is great Programming in Lua 143 Copyright ® 2005, Translation Team, www.luachina.net s = string.gsub("all lii", "l", "x", 1) print(s) --> axl lii s = string.gsub("all lii", "l", "x", 2) print(s) --> axx lii string.gsub _, count = string.gsub(str, " ", " ") _ 2200..22 %d '%d%d/%d%d/%d%d%d%d' dd/mm/yyyy s = "Deadline is 30/05/1999, firm" date = "%d%d/%d%d/%d%d%d%d" print(string.sub(s, string.find(s, date))) --> 30/05/1999 Lua . %a %c %d %l %p %s %u %w %x %z 0 '%A' print(string.gsub("hello, up-down!", "%A", ".")) --> hello..up.down. 4 4 gsub gsub Lua Programming in Lua 144 Copyright ® 2005, Translation Team, www.luachina.net ( ) . % + - * ? [ ^ $ '%' '%.' '%%' '%' '%' Lua '%' '\' '\' Lua Lua char-set '[%w_]' '[01]' '[%[%]]' _, nvow = string.gsub(text, "[AEIOUaeiou]", "") char-set '%d' '[0-9]''%x' '[0-9a-fA-F]' '[0-7]' '[01234567]'(char-set) '^' '[^0-7]' '[^\n]' '%S' '[^%s]' Lua '[a-z]' '%l' 'ç' 'ã' Lua + 1 * 0 - 0 ? 0 1 '+' '%a+' print(string.gsub("one, and two; and three", "%a+", "word")) --> word, word word; word word '%d+' i, j = string.find("the number 1298 is even", "%d+") print(i,j) --> 12 15 '*' '+' 0 . Programming in Lua 145 Copyright ® 2005, Translation Team, www.luachina.net () '%(%s*%)' '%s*' 0 '%' '[_%a][_%w]*' Lua '-' '*' 0 '[_%a][_%w]-' '[_%w]-' C '/%*.*%*/' "/*" "*/" '.*' "/*" "*/" test = "int x; /* x */ int y; /* y */" print(string.gsub(test, "/%*.*%*/", "")) --> int x; '.-' "/*" "*/" test = "int x; /* x */ int y; /* y */" print(string.gsub(test, "/%*.-%*/", "")) --> int x; int y; '?' 0 1 '[+-]?%d+' "-12""23" "+1009" '[+-]' '+' '-' '?' 0 1 Lua '^' '$' anchor if string.find(s, "^%d") then ... s if string.find(s, "^[+-]?%d+$") then ... s '%b' '%bxy' x y x y '%b()' '(' ')' print(string.gsub("a (enclosed (in) parentheses) line", "%b()", "")) Programming in Lua 146 Copyright ® 2005, Translation Team, www.luachina.net --> a line '%b()' '%b[]''%b%{%}' '%b<>' 2200..33 CCaappttuurreess Capture3 capture string.find captures pair = "name = Anna" _, _, key, value = string.find(pair, "(%a+)%s*=%s*(%a+)") print(key, value) --> name Anna '%a+' '%s*' 0 '=' find _ date = "17/7/1990" _, _, d, m, y = string.find(date, "(%d+)/(%d+)/(%d+)") print(d, m, y) --> 17 7 1990 '%d'd 1-9 d '["'].-["']' "it's all right" s = [[then he said: "it's all right"!]] a, b, c, quotedPart = string.find(s, "(["'])(.-)%1") print(quotedPart) --> it's all right print(c) --> " '.-' gsub gsub 3capture Programming in Lua 147 Copyright ® 2005, Translation Team, www.luachina.net '%d' '%' "%%" print(string.gsub("hello Lua!", "(%a)", "%1-%1")) --> h-he-el-ll-lo-o L-Lu-ua-a! : print(string.gsub("hello Lua", "(.)(.)", "%2%1")) --> ehll ouLa LaTeX \command{some text} XML some text , s = string.gsub(s, "\\(%a+){(.-)}", "<%1>%2") s the \quote{task} is to \em{change} that. gsub the task is to change that. function trim (s) return (string.gsub(s, "^%s*(.-)%s*$", "%1")) end '^' '$' '%s*' '.-' gsub string.gsub gsubstring.gsub gsub $varname varname function expand (s) s = string.gsub(s, "$(%w+)", function (n) Programming in Lua 148 Copyright ® 2005, Translation Team, www.luachina.net return _G[n] end) return s end name = "Lua"; status = "great" print(expand("$name is $status, isn't it?")) --> Lua is great, isn't it? string tostring function expand (s) return (string.gsub(s, "$(%w+)", function (n) return tostring(_G[n]) end)) end print(expand("print = $print; a = $a")) --> print = function: 0x8050ce0; a = nil loadstring $ s = "sin(3) = $[math.sin(3)]; 2^5 = $[2^5]" print((string.gsub(s, "$(%b[])", function (x) x = "return " .. string.sub(x, 2, -2) local f = loadstring(x) return f() end))) --> sin(3) = 0.1411200080598672; 2^5 = 32 "$[math.sin(3)]" "$[math.sin(3)]" string.sub "return math.sin(3)""$[2^5]" string.gsub words = {} string.gsub(s, "(%a+)", function (w) table.insert(words, w) Programming in Lua 149 Copyright ® 2005, Translation Team, www.luachina.net end) s "hello hi, again!" {"hello", "hi", "again"} string.gfind words = {} for w in string.gfind(s, "(%a)") do table.insert(words, w) end gfind for gfind words = {} for w in string.gfind(s, "%a") do table.insert(words, w) end URL URL HTTP URL '=''&''+' "%XX" XX 16 '+' "a+b = c" "a%2Bb+%3D+c" '=' name=value "&" name = "al"; query = "a+b = c"; q="yes or no" name=al&query=a%2Bb+%3D+c&q=yes+or+no URL function unescape (s) s = string.gsub(s, "+", " ") s = string.gsub(s, "%%(%x%x)", function (h) return string.char(tonumber(h, 16)) end) return s end '+' gsub '%' 16 16 tonumber 16 Programming in Lua 150 Copyright ® 2005, Translation Team, www.luachina.net print(unescape("a%2Bb+%3D+c")) --> a+b = c name=value gfind names values '&' '=' '[^&=]+' cgi = {} function decode (s) for n a m e , v a l u e in s t r i n g . g f i n d ( s , "([^&=]+)=([^&=]+)") do name = unescape(name) value = unescape(value) cgi[name] = value end end gfind name=value name=value name value unescape name value cgi escape '%' ASCII 16 0 '+' function escape (s) s = string.gsub(s, "([&=+%c])", function (c) return string.format("%%%02X", string.byte(c)) end) s = string.gsub(s, " ", "+") return s end function encode (t) local s = "" for k,v in pairs(t) do s = s .. "&" .. escape(k) .. "=" .. escape(v) end return string.sub(s, 2) -- remove first `&' end t = {name = "al", query = "a+b = c", q="yes or no"} print(encode(t)) --> q=yes+or+no&query=a%2Bb+%3D+c&name=al Programming in Lua 151 Copyright ® 2005, Translation Team, www.luachina.net 2200..44 TTrriicckkss ooff tthhee TTrraaddee string.gsub find quick-and-dirty C '/%*.-%*/' "/*" test = [[char s[] = "a /* here"; /* a tricky string */]] print(string.gsub(test, "/%*.-%*/", "")) --> char s[] = "a Lua 333MHz 200K (30K ) 1/10 '(.-)%$' $ $$ $ 333MHz 3 200K '^(.-)%$'^ 1/10 '%a*' i, j = string.find(";$% **#$hello13", "%a*") print(i,j) --> 1 0 string.find '-' '.*' Lua 70 70 '[^\n]' Programming in Lua 152 Copyright ® 2005, Translation Team, www.luachina.net 70 0 string.rep pattern = string.rep("[^\n]", 70) .. "[^\n]*" x '[xX]' function nocase (s) s = string.gsub(s, "%a", function (c) return string.format("[%s%s]", string.lower(c), string.upper(c)) end) return s end print(nocase("Hi there!")) --> [hH][iI] [tT][hH][eE][rR][eE]! s1 s2 s1 s2 gsub s1 = string.gsub(s1, "(%W)", "%%%1") s2 = string.gsub(s2, "%%", "%%%%") '%' """ "This is "great"!". """ "\1" "\1" "\x" "\ddd" ddd x function code (s) return (string.gsub(s, "\\(.)", function (x) return string.format("\\%03d", string.byte(x)) end)) end "\ddd" Programming in Lua 153 Copyright ® 2005, Translation Team, www.luachina.net function decode (s) return (string.gsub(s, "\\(%d%d%d)", function (d) return "\" .. string.char(d) end)) end ' ".-" ' s = [[follows a typical string: "This is "great"!".]] s = code(s) s = string.gsub(s, '(".-")', string.upper) s = decode(s) print(s) --> follows a typical string: "THIS IS "GREAT"!". print(decode(string.gsub(code(s), '(".-")', string.upper))) \command{string} XML string "\""\{" "\}" '\''{' '}' \x\command x \x function code (s) return (string.gsub(s, '\\(%A)', function (x) return string.format("\\%03d", string.byte(x)) end)) end string.char function decode (s) return (string.gsub(s, '\\(%d%d%d)', string.char)) end s = [[a \emph{command} is written as \\command\{text\}.]] s = code(s) s = string.gsub(s, "\\(%a+){(.-)}", "<%1>%2") Programming in Lua 154 Copyright ® 2005, Translation Team, www.luachina.net print(decode(s)) --> a command is written as \command{text}. CSV Microsoft ExcelCSV {'a b', 'a,b', 'a,"b"c', 'hello "world"!', } a b,"a,b"," a,""b""c", hello "world"!, CSV function toCSV (t) local s = "" for _,p in pairs(t) do s = s .. "," .. escapeCSV(p) end return string.sub(s, 2) -- remove first comma end function escapeCSV (s) if string.find(s, '[,"]') then s = '"' .. string.gsub(s, '"', '""') .. '"' end return s end CSV "hello""hello", "","" "hello"hello", " """ Programming in Lua 155 Copyright ® 2005, Translation Team, www.luachina.net gsub ' "("?) ' c function fromCSV (s) s = s .. ',' -- ending comma local t = {} -- table to collect fields local fieldstart = 1 repeat -- next field is quoted? (start with `"'?) if string.find(s, '^"', fieldstart) then local a, c local i = fieldstart repeat -- find closing quote a, i, c = string.find(s, '"("?)', i+1) until c ~= '"' -- quote not followed by quote? if not i then error('unmatched "') end local f = string.sub(s, fieldstart+1, i-1) table.insert(t, (string.gsub(f, '""', '"'))) fieldstart = string.find(s, ',', i) + 1 else -- unquoted; find next comma local nexti = string.find(s, ',', fieldstart) table.insert(t, string.sub(s, fieldstart, nexti-1)) fieldstart = nexti + 1 end until fieldstart > string.len(s) return t end t = fromCSV('"hello "" hello", "",""') for i, s in ipairs(t) do print(i, s) end --> 1 hello " hello --> 2 "" --> 3 Programming in Lua 156 Copyright ® 2005, Translation Team, www.luachina.net Programming in Lua 157 Copyright ® 2005, Translation Team, www.luachina.net 21 IO I/O simple model complete model I/O tableio 2211..11 II//OO I/O stdinstdout io.read io.input io.output io.input(filename) io.inputio.output io.input io.read io.write string format > io.write("sin (3) = ", math.sin(3), "\n") --> sin (3) = 0.1411200080598672 > io.write(string.format("sin (3) = %.4f\n", math.sin(3))) --> sin (3) = 0.1411 io.write(a..b..c) io.write(a,b,c) quick and dirty print write > print("hello", "Lua"); print("Hi") --> hello Lua --> Hi > io.write("hello", "Lua"); io.write("Hi", "\n") --> helloLuaHi Write print write Programming in Lua 158 Copyright ® 2005, Translation Team, www.luachina.net write print printtostringtablesfunctions nil read "*all" "*line" "*number" num num io.read("*all") Lua Lua gsub t = io.read("*all") -- read the whole file t = string.gsub(t, ...) -- do the job io.write(t) -- write the file MIME quoted-printable ASCII =XX XX = gsub 128 255 t = io.read("*all") t = string.gsub(t, "([\128-\255=])", function (c) return string.format("=%02X", string.byte(c)) end) io.write(t) 333MHz 200k 0.2 io.read("*line") nil read io.read() *all local count = 1 while true do local line = io.read() if line == nil then break end Programming in Lua 159 Copyright ® 2005, Translation Team, www.luachina.net io.write(string.format("%6d ", count), line, "\n") count = count + 1 end io.lines local lines = {} -- read the lines in table 'lines' for line in io.lines() do table.insert(lines, line) end -- sort table.sort(lines) -- write all the lines for i, l in ipairs(lines) do io.write(l, "\n") end 333MHz 4.5MB 32K 1.8 C 0.6 io.read("*number") read *number -3+5.21000 -3.4e-23 nil 6.0 -3.23 15e12 4.3 234 1000001 ... read while true do local n1, n2, n3 = io.read("*number", "*number", "*number") if not n1 then break end print(math.max(n1, n2, n3)) end io.read " *.all " gfind local pat = "(%S+)%s+(%S+)%s+(%S+)%s+" for n1, n2, n3 in string.gfind(io.read("*all"), pat) do Programming in Lua 160 Copyright ® 2005, Translation Team, www.luachina.net print(math.max(n1, n2, n3)) end n read read n nil n read Lua local size = 2^13 -- good buffer size (8K) while true do local block = io.read(size) if not block then break end io.write(block) end io.read(0) nil 2211..22 II//OO file handle C FILE* io.open C fopen "r" "w" "a" "b" open nil print(io.open("non-existent file", "r")) --> nil No such file or directory 2 print(io.open("/etc/passwd", "w")) --> nil Permission denied 13 local f = assert(io.open(filename, mode)) open assert assert read write io read/write Programming in Lua 161 Copyright ® 2005, Translation Team, www.luachina.net local f = assert(io.open(filename, "r")) local t = f:read("*all") f:close() C streamI/O io.stdinio.stdout io.stderrerror stream io.stderr:write(message) io.input() io.input(handle) handle io.output local temp = io.input() -- save current file io.input("newinput") -- open a new current file ... -- do something with new input io.input():close() -- close current file io.input(temp) -- restore previous current file 2211..22..11 II//OO Lua 8kb local lines, rest = f:read(BUFSIZE, "*line") rest chunk local BUFSIZE = 2^13 -- 8K local f = io.input(arg[1]) -- open input file local cc, lc, wc = 0, 0, 0 -- char, line, and word counts while true do local lines, rest = f:read(BUFSIZE, "*line") if not lines then break end if rest then lines = lines .. rest .. '\n' end cc = cc + string.len(lines) -- count words in the chunk Programming in Lua 162 Copyright ® 2005, Translation Team, www.luachina.net local _,t = string.gsub(lines, "%S+", "") wc = wc + t -- count newlines in the chunk _,t = string.gsub(lines, "\n", "\n") lc = lc + t end print(lc, wc, cc) 2211..22..22 Unix Windows b io.open Lua 0 0 %z *all n n DOS Unix Text Mode stdin/stdout local inp = assert(io.open(arg[1], "rb")) local out = assert(io.open(arg[2], "wb")) local data = inp:read("*all") data = string.gsub(data, "\r\n", "\n") out:write(data) assert(out:close()) > lua prog.lua file.dos file.unix validchars string.rep validchars%z local f = assert(io.open(arg[1], "rb")) Programming in Lua 163 Copyright ® 2005, Translation Team, www.luachina.net local data = f:read("*all") local validchars = "[%w%p%s]" local pattern = string.rep(validchars, 6) .. "+%z" for w in string.gfind(data, pattern) do print(w) end 4Dump 10 local f = assert(io.open(arg[1], "rb")) local block = 10 while true do local bytes = f:read(block) if not bytes then break end for b in string.gfind(bytes, ".") do io.write(string.format("%02X ", string.byte(b))) end io.write(string.rep(" ", block - string.len(bytes) + 1)) io.write(string.gsub(bytes, "%c", "."), "\n") end vip prompt> lua vip vip Unix 6C 6F 63 61 6C 20 66 20 3D 20 local f = 61 73 73 65 72 74 28 69 6F 2E assert(io. 6F 70 65 6E 28 61 72 67 5B 31 open(arg[1 5D 2C 20 22 72 62 22 29 29 0A ], "rb")). ... 22 25 63 22 2C 20 22 2E 22 29 "%c", ".") 2C 20 22 5C 6E 22 29 0A 65 6E , "\n").en 64 0A d. 2211..33 tmpfile read/write 4 Programming in Lua 164 Copyright ® 2005, Translation Team, www.luachina.net flush write io.flush() f:flush() f seek filehandle:seek(whence,offset)Whence "set""cur" "end"offset whence offset whence "cur"offset 0 file:seek() file:seek("set") 0 file:seek("end") function fsize (file) local current = file:seek() -- get current position local size = file:seek("end") -- get file size file:seek("set", current) -- restore position return size end nil Programming in Lua 165 Copyright ® 2005, Translation Team, www.luachina.net 22 tableos Lua Lua ANSI C ANSI ANSI Lua posix POSIX 1 luasocket os.rename os.remove 2222..11 DDaattee TTiimmee time date Lua time year a full year month 01-12 day 01-31 hour 01-31 min 00-59 sec 00-59 isdst a boolean, true if daylight saving 12:00:00 Unix 1970 1 1 00:00:00 -- obs: 10800 = 3*60*60 (3 hours) print(os.time{year=1970, month=1, day=1, hour=0}) --> 10800 print(os.time{year=1970, month=1, day=1, hour=0, sec=1}) --> 10801 print(os.time{year=1970, month=1, day=1}) --> 54000 (obs: 54000 = 10800 + 12*60*60) Programming in Lua 166 Copyright ® 2005, Translation Team, www.luachina.net data time "*t" temp = os.date("*t", 906000490) {year = 1998, month = 9, day = 16, yday = 259, wday = 4, hour = 23, min = 48, sec = 10, isdst = false} wday 1yday 1 "*t" os.data "%" print(os.date("today is %A, in %B")) --> today is Tuesday, in May print(os.date("%x", 906000490)) --> 09/16/1998 "%B" "setembro""%x" "16/09/98" 1998 16 23:48:10 %a abbreviated weekday name (e.g., Wed) %A full weekday name (e.g., Wednesday) %b abbreviated month name (e.g., Sep) %B full month name (e.g., September) %c date and time (e.g., 09/16/98 23:48:10) %d day of the month (16) [01-31] %H hour, using a 24-hour clock (23) [00-23] %I hour, using a 12-hour clock (11) [01-12] %M minute (48) [00-59] %m month (09) [01-12] %p either "am" or "pm" (pm) %S second (10) [00-61] %w weekday (3) [0-6 = Sunday-Saturday] %x date (e.g., 09/16/98) %X time (e.g., 23:48:10) Programming in Lua 167 Copyright ® 2005, Translation Team, www.luachina.net %Y full year (1998) %y two-digit year (98) [00-99] %% the character '%' date%c %x%X %c mm/dd/yyyy "%m/%d/%Y" os.clock CPU local x = os.clock() local s = 0 for i=1,100000 do s = s + i end print(string.format("elapsed time: %.2f\n", os.clock() - x)) 2222..22 os.exit os.getenv print(os.getenv("HOME")) --> /home/lua nil os.execute C system Unix DOS-Windows function createDir (dirname) os.execute("mkdir " .. dirname) end os.execute os.setlocale Lua localesetlocale category collate"ctype" controls the types of individual characters (e.g., what is a letter) and the conversion between lower and upper cases; "monetary" Lua "numeric""time" os.date all all setlocale nil print(os.setlocale("ISO-8859-1", "collate")) --> ISO-8859-1 numeric Programming in Lua 168 Copyright ® 2005, Translation Team, www.luachina.net Lua print3,4 5 -- print(os.setlocale('pt_BR')) --> pt_BR print(3,4) --> 3 4 print(3.4) --> stdin:1: malformed number near `3.4' The category "numeric" is a little tricky. Although Portuguese and other Latin languages use a comma instead of a point to represent decimal numbers, the locale does not change the way that Lua parses numbers (among other reasons because expressions like print(3,4) already have a meaning in Lua). Therefore, you may end with a system that cannot recognize numbers with commas, but cannot understand numbers with points either: -- set locale for Portuguese-Brazil print(os.setlocale('pt_BR')) --> pt_BR print(3,4) --> 3 4 print(3.4) --> stdin:1: malformed number near '3.4' 5 Programming in Lua 169 Copyright ® 2005, Translation Team, www.luachina.net 23 Debug debug Lua Lua C API Lua debug Lua C Debug debug debug debug (sacred truths) debug debug = nil debug (introspective) hooks Hooks Debug (stack level) debug 1( debug ) 2 2233..11 IInnttrroossppeeccttiivvee debug debug.getinfo foo debug.getinfo(foo) source loadstring source source @ short_srcsource 60 linedefinedsource what foo Lua "Lua" C "C" Lua chunk "main" name namewhatW"global""local" Programming in Lua 170 Copyright ® 2005, Translation Team, www.luachina.net "method""field" "" Lua nups upvalues func foo C Lua whatnamenamewhat n debug.getinfo(n) n n=1n=0 C getinfo n debug.getinfo nil n debug.getinfo table currentlinefunc n Lua Lua getinfo getinfo Lua debugLua keeps debug information in a form that does not impair program execution getinfo 'n' selects fields name and namewhat 'f' selects field func 'S' selects fields source, short_src, what, and linedefined 'l' selects field currentline 'u' selects field nup debug.getinfo traceback function traceback () local level = 1 while true do local info = debug.getinfo(level, "Sl") if not info then break end if info.what == "C" then -- is a C function? print(level, "C function") else -- a Lua function print(string.format("[%s]:%d", info.short_src, info.currentline)) Programming in Lua 171 Copyright ® 2005, Translation Team, www.luachina.net end level = level + 1 end end getinfo debug debug.tracebackdebug.traceback 2233..11..11 debug getlocal getlocal nil debug.getinfo Lua function foo (a,b) local x do local c = a - b end local a = 1 while true do local name, value = debug.getlocal(1, a) if not name then break end print(name, value) a = a + 1 end end foo(10, 20) a 10 b 20 x nil a 4 1 a2 b3 x4 a getlocal c name value debug.setlocal Programming in Lua 172 Copyright ® 2005, Translation Team, www.luachina.net nil 2233..11..22 UUppvvaalluueess debug getupvalue Lua upvalues upvalues getupvalue upvalue Lua upvalue (refer) upvalues upvalue relevant ebug.setupvalue upvalues upvalues upvalue setlocal upvalue nil upvalue function getvarvalue (name) local value, found -- try local variables local i = 1 while true do local n, v = debug.getlocal(2, i) if not n then break end if n == name then value = v found = true end i = i + 1 end if found then return value end -- try upvalues local func = debug.getinfo(2).func i = 1 while true do local n, v = debug.getupvalue(func, i) if not n then break end Programming in Lua 173 Copyright ® 2005, Translation Team, www.luachina.net if n == name then return v end i = i + 1 end -- not found; get global return getfenv(func)[name] end upvalues debug.getinfo(2).func upvalues debug.getlocal debug.getinfo 2 2233..22 HHooookkss debug hook hook Lua call return Lua line count Lua hooks "call""return""line" "count" line hook debug.getinfo debug.sethook hook hook count callreturn line 'c''r' 'l' mask hooks sethook debug.sethook(print, "l") print hook Lua line print getinfo function trace (event, line) local s = debug.getinfo(2).short_src print(s .. ":" .. line) end Programming in Lua 174 Copyright ® 2005, Translation Team, www.luachina.net debug.sethook(trace, "l") 2233..33 PPrrooffiilleess debug profiling profile For a profile with timing C hook Lua profiles Lua profiler local Counters = {} local Names = {} profiling Lua hook 1 hook local function hook () local f = debug.getinfo(2, "f").func if Counters[f] == nil then -- first time `f' is called? Counters[f] = 1 Names[f] = debug.getinfo(2, "Sn") else -- only increment the counter Counters[f] = Counters[f] + 1 end end hook chunk profiler prompt> lua profiler main-prog arg[1] hook local f = assert(loadfile(arg[1])) debug.sethook(hook, "c") -- turn on the hook Programming in Lua 175 Copyright ® 2005, Translation Team, www.luachina.net f() -- run the main program debug.sethook() -- turn off the hook Lua file:line C function getname (func) local n = Names[func] if n.what == "C" then return n.name end local loc = string.format("[%s]:%s", n.short_src, n.linedefined) if n.namewhat ~= "" then return string.format("%s (%s)", loc, n.name) else return string.format("%s", loc) end end for func, count in pairs(Counters) do print(getname(func), count) end profiler Section 10.2 [markov.lua]:4 884723 write 10000 [markov.lua]:0 (f) 1 read 31103 sub 884722 [markov.lua]:1 (allwords) 1 [markov.lua]:20 (prefix) 894723 find 915824 [markov.lua]:26 (insert) 884723 random 10000 sethook 1 insert 884723 Programming in Lua 176 Copyright ® 2005, Translation Team, www.luachina.net allwords 884,723 write(io.write) 10,000 profiler profiler Programming in Lua 177 Copyright ® 2005, Translation Team, www.luachina.net C API Programming in Lua 178 Copyright ® 2005, Translation Team, www.luachina.net 24 C API Lua Lua Lua Lua Lua lua Lua Lua 500 Lua Lua Lua Lua Lua C ( ) Lua Lua (Lua ) C Lua C Lua Lua C C API Lua C Lua C API C API C Lua Lua Lua Lua C Lua API C API C Lua C API \"segmentation fault\" API API C Lua Lua Lua API Lua lua.clmathlib.clstrlib.c C / C C Lua API C Lua C Lua Programming in Lua 179 Copyright ® 2005, Translation Team, www.luachina.net Lua C Lua C 24.2 2244..11 Lua #include #include #include #include int main (void) { char buff[256]; int error; lua_State *L = lua_open(); /* opens Lua */ luaopen_base(L); /* opens the basic library */ luaopen_table(L); /* opens the table library */ luaopen_io(L); /* opens the I/O library */ luaopen_string(L); /* opens the string lib. */ luaopen_math(L); /* opens the math lib. */ while (fgets(buff, sizeof(buff), stdin) != NULL) { error = luaL_loadbuffer(L, buff, strlen(buff), "line") || lua_pcall(L, 0, 0, 0); if (error) { fprintf(stderr, "%s", lua_tostring(L, -1)); lua_pop(L, 1);/* pop error message from the stack */ } } lua_close(L); return 0; } lua.h Lua Lua lua_open Lua lua_pcall/ Lua Programming in Lua 180 Copyright ® 2005, Translation Team, www.luachina.net Lua lua.h lua_ lauxlib.h auxlib luaL_luaL_loadbuffer lua.h Lua auxlib API economy and orthogonality auxlib auxlib Lua API Lua lua_State Lua Lua reentrant lua_open state lua_open print Lua lualib.h luaopen_io io table I/O io.read,io.write Lua state C luaL_loadbuffer Lua chunk C lua_pcall chunk luaL_laodbuffer lua_pcall lua_tostring lua_pop C Lua Lua state #include #include #include void error (lua_State *L, const char *fmt, ...) { va_list argp; va_start(argp, fmt); vfprintf(stderr, argp); va_end(argp); Programming in Lua 181 Copyright ® 2005, Translation Team, www.luachina.net lua_close(L); exit(EXIT_FAILURE); } . Lua C/C++ lua.h C #ifdef __cplusplus extern "C" { #endif ... #ifdef __cplusplus } #endif C C++ lua.h extern "C" { #include } lua.hpp C++ 2244..22 Lua C Lua a[k]=v k v metatables a C (settable) C union lua_Value Lua settable void lua_settable (lua_Value a, lua_Value k, lua_Value v); Lua C/C++Java,Fortran Lua Lua C Lua Programming in Lua 182 Copyright ® 2005, Translation Team, www.luachina.net Lua API lua_Value Lua C Lua Lua Lua Lua Lua C combinatorial explosion Lua C API luaL_loadbuffer chunk lua_pcall Lua LIFO Lua 2244..22..11 API C Lua nil lua_pushnildouble lua_pushnumber C lua_pushbooleanchar*'\0' lua_pushlstringC '\0'const char* lua_pushstring void lua_pushnil (lua_State *L); void lua_pushboolean (lua_State *L, int bool); void lua_pushnumber (lua_State *L, double n); void lua_pushlstring (lua_State *L, const char *s, size_t length); void lua_pushstring (lua_State *L, const char *s); C userdata Lua lua_pushlstring lua_pushstring strlen Lua C Lua C Lua Lua Lua C 20 lua.h LUA_MINSTACK Programming in Lua 183 Copyright ® 2005, Translation Team, www.luachina.net int lua_checkstack (lua_State *L, int sz); 2244..22..22 API 1 2 -1 -2 lua_tostring(L, -1) API lua_is** Lua lua_isnumber,lua_isstring,lua_istable int lua_is... (lua_State *L, int index); lua_isnumber lua_isstring lua_isstring lua_type lua_is* lua.h LUA_TNIL LUA_TBOOLEAN LUA_TNUMBER LUA_TSTRING LUA_TTABLE LUA_TFUNCTIONLUA_TUSERDATA LUA_TTHREAD switch lua_to* int lua_toboolean (lua_State *L, int index); double lua_tonumber (lua_State *L, int index); const char * lua_tostring (lua_State *L, int index); size_t lua_strlen (lua_State *L, int index); lua_tobooleanlua_tonumber lua_strlen 0 NULL ANSI C 0 lua_is* lua_is* NULL Lua_tostring constLua Programming in Lua 184 Copyright ® 2005, Translation Team, www.luachina.net C Lua Lua Lua_string 0 0lua_strlen (assert) const char *s = lua_tostring(L, -1); /* any Lua string */ size_t l = lua_strlen(L, -1); /* its length */ assert(s[l] == '\0'); assert(strlen(s) <= l); 2244..22..33 C API int lua_gettop (lua_State *L); void lua_settop (lua_State *L, int index); void lua_pushvalue (lua_State *L, int index); void lua_remove (lua_State *L, int index); void lua_insert (lua_State *L, int index); void lua_replace (lua_State *L, int index); lua_gettop -x gettop-x+1lua_settop nillua_settop(L,0) lua_settop API n #define lua_pop(L,n) lua_settop(L, -(n)-1) lua_pushvalue lua_remove lua_insert lua_replace lua_settop(L, -1); /* set top to its current value */ lua_insert(L, -1); /* move top element to the top */ dump static void stackDump (lua_State *L) { Programming in Lua 185 Copyright ® 2005, Translation Team, www.luachina.net int i; int top = lua_gettop(L); for (i = 1; i <= top; i++) { /* repeat for each level */ int t = lua_type(L, i); switch (t) { case LUA_TSTRING: /* strings */ printf("`%s'", lua_tostring(L, i)); break; case LUA_TBOOLEAN: /* booleans */ printf(lua_toboolean(L, i) ? "true" : "false"); break; case LUA_TNUMBER: /* numbers */ printf("%g", lua_tonumber(L, i)); break; default: /* other values */ printf("%s", lua_typename(L, t)); break; } printf(" "); /* put a separator */ } printf("\n"); /* end the listing */ } %g table lua_typename stackDump API #include #include static void stackDump (lua_State *L) { ... } Programming in Lua 186 Copyright ® 2005, Translation Team, www.luachina.net int main (void) { lua_State *L = lua_open(); lua_pushboolean(L, 1); lua_pushnumber(L, 10); lua_pushnil(L); lua_pushstring(L, "hello"); stackDump(L); /* true 10 nil `hello' */ lua_pushvalue(L, -4); stackDump(L); /* true 10 nil `hello' true */ lua_replace(L, 3); stackDump(L); /* true 10 true `hello' */ lua_settop(L, 6); stackDump(L); /* true 10 true `hello' nil nil */ lua_remove(L, -3); stackDump(L); /* true 10 true nil nil */ lua_settop(L, -5); stackDump(L); /* true */ lua_close(L); return 0; } 2244..33 CC AAPPII C++ JAVA C Lua C setjmp C++ Lua Lua Lua Lua API API longjmp Lua C long jump Lua Lua C Programming in Lua 187 Copyright ® 2005, Translation Team, www.luachina.net 2244..33..11 Lua Lua Lua setjmp Lua "not enough memory" panic lua_atpanic panic API lua_openlua_closelua_pcall lua_load luaL_loadfile Lua panic Lua lua_pcall lua_pcall lua consistent Lua C lua_cpcall Lua lua.c 2244..33..22 Lua Lua Lua C C Lua C poke add-ons Lua C Lua C lua_error luaL_error Lua_error Lua lua_pcall Programming in Lua 188 Copyright ® 2005, Translation Team, www.luachina.net 25 LUA , LUA C PP LUA LUA LUA -- configuration file for program `pp' -- define window size width = 200 height = 300 LUA API width height #include #include #include void load (char *filename, int *width, int *height) { lua_State *L = lua_open(); luaopen_base(L); luaopen_io(L); luaopen_string(L); luaopen_math(L); if (luaL_loadfile(L, filename) || lua_pcall(L, 0, 0, 0)) error(L, "cannot run configuration file: %s", lua_tostring(L, -1)); lua_getglobal(L, "width"); lua_getglobal(L, "height"); if (!lua_isnumber(L, -2)) error(L, "`width' should be a number\n"); if (!lua_isnumber(L, -1)) Programming in Lua 189 Copyright ® 2005, Translation Team, www.luachina.net error(L, "`height' should be a number\n"); *width = (int)lua_tonumber(L, -2); *height = (int)lua_tonumber(L, -1); lua_close(L); } LUA luaL_loadfile filename lua_pcall index -1 lua_tostring error 24.1 lua_getglobal width index -2 height index -1 1 2 lua_isnumber lua_tonumber double (int) Lua ? lua lua lua -- configuration file for program 'pp' if getenv("DISPLAY") == ":0.0" then width = 300; height = 300 else width = 200; height = 200 end C lua 2255..11 Lua Programming in Lua 190 Copyright ® 2005, Translation Team, www.luachina.net RGB C [0,255] Lua [0,1] -- configuration file for program 'pp' width = 200 height = 300 background_red = 0.30 background_green = 0.10 background_blue = 0 WHITEbackground = WHITE table background = {r=0.30, g=0.10, b=0} BLUE = {r=0, g=0, b=1} ... background = BLUE C lua_getglobal(L, "background"); if (!lua_istable(L, -1)) error(L, "`background' is not a valid color table"); red = getfield("r"); green = getfield("g"); blue = getfield("b"); backgroud table getfield API #define MAX_COLOR 255 /* assume that table is on the stack top */ int getfield (const char *key) { Programming in Lua 191 Copyright ® 2005, Translation Team, www.luachina.net int result; lua_pushstring(L, key); lua_gettable(L, -2); /* get background[key] */ if (!lua_isnumber(L, -1)) error(L, "invalid component in background color"); result = (int)lua_tonumber(L, -1) * MAX_COLOR; lua_pop(L, 1); /* remove number */ return result; } getfield key value Lua API lua_gettable table key key value getfield table lua_pushstring key table -2 getfield table C table struct ColorTable { char *name; unsigned char red, green, blue; } colortable[] = { {"WHITE", MAX_COLOR, MAX_COLOR, MAX_COLOR}, {"RED", MAX_COLOR, 0, 0}, {"GREEN", 0, MAX_COLOR, 0}, {"BLUE", 0, 0, MAX_COLOR}, {"BLACK", 0, 0, 0}, ... {NULL, 0, 0, 0} /* sentinel */ }; table WHITE = {r=1, g=1, b=1} RED = {r=1, g=0, b=0} ... C table setfield field Programming in Lua 192 Copyright ® 2005, Translation Team, www.luachina.net field lua_settable /* assume that table is at the top */ void setfield (const char *index, int value) { lua_pushstring(L, index); lua_pushnumber(L, (double)value/MAX_COLOR); lua_settable(L, -3); } API lua_settable lua_settable table key value tableSetfield table (-1) index value table -3 Setcolor table table void setcolor (struct ColorTable *ct) { lua_newtable(L); /* creates a table */ setfield("r", ct->red); /* table.r = ct->r */ setfield("g", ct->green); /* table.g = ct->g */ setfield("b", ct->blue); /* table.b = ct->b */ lua_setglobal(ct->name); /* 'name' = table */ } lua_newtable table setfield table lua_setglobal table int i = 0; while (colortable[i].name != NULL) setcolor(&colortable[i++]); background = "BLUE" background table string background table string lua_getglobal(L, "background"); if (lua_isstring(L, -1)) { const char *name = lua_tostring(L, -1); int i = 0; Programming in Lua 193 Copyright ® 2005, Translation Team, www.luachina.net while (colortable[i].name != NULL && strcmp(colorname, colortable[i].name) != 0) i++; if (colortable[i].name == NULL) /* string not found? */ error(L, "invalid color name (%s)", colorname); else { /* use colortable[i] */ red = colortable[i].red; green = colortable[i].green; blue = colortable[i].blue; } } else if (lua_istable(L, -1)) { red = getfield("r"); green = getfield("g"); blue = getfield("b"); } else error(L, "invalid value for `background'"); C Lua Lua WHITE WITE background nil(WITE ) background nilbackground "white""WHITE" "White"( table ) 2255..22 LLuuaa Lua Lua API lua_pcall function f (x, y) return (x^2 * math.sin(y))/(1 - x) end Programming in Lua 194 Copyright ® 2005, Translation Team, www.luachina.net C x,y z=f(x,y) lua C /* call a function `f' defined in Lua */ double f (double x, double y) { double z; /* push functions and arguments */ lua_getglobal(L, "f"); /* function to be called */ lua_pushnumber(L, x); /* push 1st argument */ lua_pushnumber(L, y); /* push 2nd argument */ /* do the call (2 arguments, 1 result) */ if (lua_pcall(L, 2, 1, 0) != 0) error(L, "error running function `f': %s", lua_tostring(L, -1)); /* retrieve result */ if (!lua_isnumber(L, -1)) error(L, "function `f' must return a number"); z = lua_tonumber(L, -1); lua_pop(L, 1); /* pop returned value */ return z; } lua_pcall Lua lua_pcall nil lua_pcall n -n -1 lua_pcall lua_pcall 0 lua_pcall lua_pcall 0 lua_pcall LUA_ERRRUN lua_pcall LUA_ERRMEM Lua Programming in Lua 195 Copyright ® 2005, Translation Team, www.luachina.net lua_pcall LUA_ERRERR 2255..33 C vararg Lua call_va call_va("f", "dd>d", x, y, &z); "dd>d" double double 'd' double'i' integer's' strings'>' '>' #include void call_va (const char *func, const char *sig, ...) { va_list vl; int narg, nres; /* number of arguments and results */ va_start(vl, sig); lua_getglobal(L, func); /* get function */ /* push arguments */ narg = 0; while (*sig) { /* push arguments */ switch (*sig++) { case 'd': /* double argument */ lua_pushnumber(L, va_arg(vl, double)); break; case 'i': /* int argument */ lua_pushnumber(L, va_arg(vl, int)); break; case 's': /* string argument */ lua_pushstring(L, va_arg(vl, char *)); break; Programming in Lua 196 Copyright ® 2005, Translation Team, www.luachina.net case '>': goto endwhile; default: error(L, "invalid option (%c)", *(sig - 1)); } narg++; luaL_checkstack(L, 1, "too many arguments"); } endwhile: /* do the call */ nres = strlen(sig); /* number of expected results */ if (lua_pcall(L, narg, nres, 0) != 0) /* do the call */ error(L, "error running function `%s': %s", func, lua_tostring(L, -1)); /* retrieve results */ nres = -nres; /* stack index of first result */ while (*sig) { /* get results */ switch (*sig++) { case 'd': /* double result */ if (!lua_isnumber(L, nres)) error(L, "wrong result type"); *va_arg(vl, double *) = lua_tonumber(L, nres); break; case 'i': /* int result */ if (!lua_isnumber(L, nres)) error(L, "wrong result type"); *va_arg(vl, int *) = (int)lua_tonumber(L, nres); break; case 's': /* string result */ if (!lua_isstring(L, nres)) error(L, "wrong result type"); *va_arg(vl, const char * * ) = l u a _ t o s t r i n g ( L , n r e s ) ; break; Programming in Lua 197 Copyright ® 2005, Translation Team, www.luachina.net default: error(L, "invalid option (%c)", *(sig - 1)); } nres++; } va_end(vl); } func lua_pcall call_va Programming in Lua 198 Copyright ® 2005, Translation Team, www.luachina.net 26 C Lua C Lua Lua C Lua C Lua C C Lua Lua C Lua C C Lua Lua C C Lua C C the function returns (in C) the number of results it is leaving on the stack. Lua C index=1 C Lua Lua C C C index=1 2266..11 CC sin static int l_sin (lua_State *L) { double d = lua_tonumber(L, 1); /* get argument */ lua_pushnumber(L, sin(d)); /* push result */ return 1; /* number of results */ } Lua lua.h lua_CFunction typedef int (*lua_CFunction) (lua_State *L); C C Lua state Lua Lua Programming in Lua 199 Copyright ® 2005, Translation Team, www.luachina.net lua_pushcfunction C Lua function quick-and-dirty lua.c lua_open lua_pushcfunction(l, l_sin); lua_setglobal(l, "mysin"); function function mysin Lua Lua mysin C Lua sin sin luaL_checknumber static int l_sin (lua_State *L) { double d = luaL_checknumber(L, 1); lua_pushnumber(L, sin(d)); return 1; /* number of results */ } mysin('a'), bad argument #1 to 'mysin' (number expected, got string) luaL_checknumber number1"mysin" "number""string" Lua ANSI C POSIX dir dir("/home/lua"){".", "..", "src", "bin", "lib"} nil #include #include 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); Programming in Lua 200 Copyright ® 2005, Translation Team, www.luachina.net 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 */ } luaL_checkstring luaL_checknumber l_dir Lua lua_newtablelua_pushstring lua_settable l_dir closedir 29 2266..22 CC Lua Lua chunk table Lua C C Lua chunk C Lua chunk Lua C C Lua Lua Lua C Lua C public/extern C Programming in Lua 201 Copyright ® 2005, Translation Team, www.luachina.net static C Lua C C luaL_openlib C table l_dir static int l_dir (lua_State *L) { ... /* as before */ } luaL_reg static const struct luaL_reg mylib [] = { {"dir", l_dir}, {NULL, NULL} /* sentinel */ }; l_dir {NULL, NULL} luaL_openlib int luaopen_mylib (lua_State *L) { luaL_openlib(L, "mylib", mylib, 0); return 1; } luaL_openlib ( reuse) mylib name-function luaL_openlib upvalues upvalues 0luaL_openlib luaL_openlib 1 Lua The luaopen_mylib function returns 1 to return this value to Lua Lua Lua Lua Lua 8.2 windows .dll linux .so Lua loadlib mylib = loadlib("fullname-of-your-library", "luaopen_mylib") luaopen_mylib Lua C mylib luaopen_mylib C Programming in Lua 202 Copyright ® 2005, Translation Team, www.luachina.net mylib() luaopen_mylib Lua Lua mylib.h int luaopen_mylib (lua_State *L); #define LUA_EXTRALIBS { "mylib", luaopen_mylib }, LUA_EXTRALIBS struct luaL_reg[] LUA_USERCONFIG -DLUA_USERCONFIG=\"mylib.h\" shell C lua.c mylib.h LUA_EXTRALIBS Programming in Lua 203 Copyright ® 2005, Translation Team, www.luachina.net 27 C API C string C Lua 2277..11 Lua table table lua_settable lua_gettable Lua economy and simplicityAPI API void lua_rawgeti (lua_State *L, int index, int key); void lua_rawseti (lua_State *L, int index, int key); lua_rawgeti lua_rawseti index table key table t otherwiseyou must compensate for the new item in the stack lua_rawgeti(L,t,key) lua_pushnumber(L, key); lua_rawget(L, t); lua_rawseti(L, t, key) t lua_pushnumber(L, key); lua_insert(L, -2); /* put 'key' below previous value */ lua_rawset(L, t); raw table metamethods l_dir lua_pushnumber(L, i++); /* key */ lua_pushstring(L, entry->d_name); /* value */ lua_settable(L, -3); Programming in Lua 204 Copyright ® 2005, Translation Team, www.luachina.net lua_pushstring(L, entry->d_name); /* value */ lua_rawseti(L, -2, i++); /* set table at key 'i' */ map int l_map (lua_State *L) { int i, n; /* 1st argument must be a table (t) */ luaL_checktype(L, 1, LUA_TTABLE); /* 2nd argument must be a function (f) */ luaL_checktype(L, 2, LUA_TFUNCTION); n = luaL_getn(L, 1); /* get size of table */ for (i=1; i<=n; i++) { lua_pushvalue(L, 2); /* push f */ lua_rawgeti(L, 1, i); /* push t[i] */ lua_call(L, 1, 1); /* call f(t[i]) */ lua_rawseti(L, 1, i); /* t[i] = result */ } return 0; /* no results */ } luaL_checktype lauxlib.h luaL_getn table.getn luaL_getn lua_call lua_pcall lua_call lua_call 2277..22 C lua C lua C Lua API Programming in Lua 205 Copyright ® 2005, Translation Team, www.luachina.net API lua_pushlstring s i j i j lua lua_pushlstring(L, s+i, j-i+1); table split("hi,,there", ",") {"hi", "", "there"} static int l_split (lua_State *L) { const char *s = luaL_checkstring(L, 1); const char *sep = luaL_checkstring(L, 2); const char *e; int i = 1; lua_newtable(L); /* result */ /* repeat for each separator */ while ((e = strchr(s, *sep)) != NULL) { lua_pushlstring(L, s, e-s); /* push substring */ lua_rawseti(L, -2, i++); s = e + 1; /* skip separator */ } /* push last substring */ lua_pushstring(L, s); lua_rawseti(L, -2, i); return 1; /* return the table */ } Lua API lua_concat Lua .. metamethods lua_concat(L,n)() n lua_pushfstring Programming in Lua 206 Copyright ® 2005, Translation Team, www.luachina.net const char *lua_pushfstring (lua_State *L, const char *fmt, ...); C sprintf fmt sprintf Lua %% '%' %s%d%f Lua doubles %c lua_concat lua_pushfstring 11.6 buffer Auxlib buffer I/O buffers buffer buffer Lua lua_pushlstring lua_concat 11.6 buffer Auxlib buffer string.upper lstrlib.c static int str_upper (lua_State *L) { size_t l; size_t i; luaL_Buffer b; const char *s = luaL_checklstr(L, 1, &l); luaL_buffinit(L, &b); for (i=0; isize = n; return 1; /* new userdatum is already on the stack */ } luaL_checkint luaL_checknumber newarray Lua a = array.new(1000) array.set(array, index, value) metatables array[index] = value static int setarray (lua_State *L) { NumArray *a = (NumArray *)lua_touserdata(L, 1); int index = luaL_checkint(L, 2); double value = luaL_checknumber(L, 3); luaL_argcheck(L, a != NULL, 1, "`array' expected"); luaL_argcheck(L, 1 <= index && index <= a->size, 2, "index out of range"); a->values[index-1] = value; return 0; } luaL_argcheck setarray array.set(a, 11, 0) --> stdin:1: bad argument #1 to 'set' ('array' expected) static int getarray (lua_State *L) { NumArray *a = (NumArray *)lua_touserdata(L, 1); int index = luaL_checkint(L, 2); Programming in Lua 214 Copyright ® 2005, Translation Team, www.luachina.net luaL_argcheck(L, a != NULL, 1, "'array' expected"); luaL_argcheck(L, 1 <= index && index <= a->size, 2, "index out of range"); lua_pushnumber(L, a->values[index-1]); return 1; } static int getsize (lua_State *L) { NumArray *a = (NumArray *)lua_touserdata(L, 1); luaL_argcheck(L, a != NULL, 1, "`array' expected"); lua_pushnumber(L, a->size); return 1; } static const struct luaL_reg arraylib [] = { {"new", newarray}, {"set", setarray}, {"get", getarray}, {"size", getsize}, {NULL, NULL} }; int luaopen_array (lua_State *L) { luaL_openlib(L, "array", arraylib, 0); return 1; } luaL_openlib arraylib name-function Lua a = array.new(1000) print(a) --> userdata: 0x8064d48 print(array.size(a)) --> 1000 for i=1,1000 do array.set(a, i, 1/i) end Programming in Lua 215 Copyright ® 2005, Translation Team, www.luachina.net print(array.get(a, 10)) --> 0.1 Pentium/Linux 100K 800KB Lua 1.5MB 2288..22 MMeettaattaabblleess array.set(io.stdin, 1, 0)io.stdin (FILE*) userdatum userdatum array.set core dumpindex-out-of-range Lua C C Lua core dump userdata metatable userdata metatables metatable metatable metatable Lua userdatum metatable metatable userdatum metatable metatable registry upvalue Lua registry C metatable registry "LuaBook.array" int luaL_newmetatable (lua_State *L, const char *tname); void luaL_getmetatable (lua_State *L, const char *tname); void *luaL_checkudata (lua_State *L, int index, const char *tname); luaL_newmetatable metatable registry key key luaL_getmetatable registry tname metatableluaL_checkudata metatable usertatum metatable NULL userdata userdata Programming in Lua 216 Copyright ® 2005, Translation Team, www.luachina.net metatable int luaopen_array (lua_State *L) { luaL_newmetatable(L, "LuaBook.array"); luaL_openlib(L, "array", arraylib, 0); return 1; } newarray metatable static int newarray (lua_State *L) { int n = luaL_checkint(L, 1); size_t nbytes = sizeof(NumArray) + (n - 1)*sizeof(double); NumArray *a = (NumArray *)lua_newuserdata(L, nbytes); luaL_getmetatable(L, "LuaBook.array"); lua_setmetatable(L, -2); a->size = n; return 1; /* new userdatum is already on the stack */ } lua_setmetatable metatable userdatum setarraygetarray getsize static NumArray *checkarray (lua_State *L) { void *ud = luaL_checkudata(L, 1, "LuaBook.array"); luaL_argcheck(L, ud != NULL, 1, "`array' expected"); return (NumArray *)ud; } checkarray getsize static int getsize (lua_State *L) { NumArray *a = checkarray(L); lua_pushnumber(L, a->size); return 1; } setarray getarray index static double *getelem (lua_State *L) { Programming in Lua 217 Copyright ® 2005, Translation Team, www.luachina.net NumArray *a = checkarray(L); int index = luaL_checkint(L, 2); luaL_argcheck(L, 1 <= index && index <= a->size, 2, "index out of range"); /* return element address */ return &a->values[index - 1]; } getelem setarray getarray static int setarray (lua_State *L) { double newvalue = luaL_checknumber(L, 3); *getelem(L) = newvalue; return 0; } static int getarray (lua_State *L) { lua_pushnumber(L, *getelem(L)); return 1; } array.get(io.stdin, 10) error: bad argument #1 to 'getarray' ('array' expected) 2288..33 userdata a = array.new(1000) print(a:size()) --> 1000 a:set(10, 3.4) print(a:get(10)) --> 3.4 a:size() a.size(a) a.size getsize __index metamethod key userdata userdata key Programming in Lua 218 Copyright ® 2005, Translation Team, www.luachina.net local metaarray = getmetatable(array.new(1)) metaarray.__index = metaarray metaarray.set = array.set metaarray.get = array.get metaarray.size = array.size metatablemetatable metaarray Lua userdata metatable Lua metatable metaarray.__index metaarray a.size Lua a size userdatumLua a metatable __index__indexmetaarraymetaarray.size array.size, a.size(a) array.size(a) C newC getsizegetarray setarray static const struct luaL_reg arraylib_f [] = { {"new", newarray}, {NULL, NULL} }; static const struct luaL_reg arraylib_m [] = { {"set", setarray}, {"get", getarray}, {"size", getsize}, {NULL, NULL} }; luaopen_array metatable __index int luaopen_array (lua_State *L) { luaL_newmetatable(L, "LuaBook.array"); lua_pushstring(L, "__index"); lua_pushvalue(L, -2); /* pushes the metatable */ lua_settable(L, -3); /* metatable.__index = metatable */ Programming in Lua 219 Copyright ® 2005, Translation Team, www.luachina.net luaL_openlib(L, NULL, arraylib_m, 0); luaL_openlib(L, "array", arraylib_f, 0); return 1; } luaL_openlib NULL luaL_openlib upvalues metatable luaL_openlib luaL_openlib new __tostring print(a) array(1000) int array2string (lua_State *L) { NumArray *a = checkarray(L); lua_pushfstring(L, "array(%d)", a->size); return 1; } lua_pushfstring metatable array2string arraylib_m array2string static const struct luaL_reg arraylib_m [] = { {"__tostring", array2string}, {"set", setarray}, ... }; 2288..44 a:get(i) a[i] setarray getarray Lua local metaarray = getmetatable(newarray(1)) metaarray.__index = array.get metaarray.__newindex = array.set Programming in Lua 220 Copyright ® 2005, Translation Team, www.luachina.net a = array.new(1000) a[10] = 3.4 -- setarray print(a[10]) -- getarray --> 3.4 C int luaopen_array (lua_State *L) { luaL_newmetatable(L, "LuaBook.array"); luaL_openlib(L, "array", arraylib, 0); /* now the stack has the metatable at index 1 and 'array' at index 2 */ lua_pushstring(L, "__index"); lua_pushstring(L, "get"); lua_gettable(L, 2); /* get array.get */ lua_settable(L, 1); /* metatable.__index = array.get */ lua_pushstring(L, "__newindex"); lua_pushstring(L, "set"); lua_gettable(L, 2); /* get array.set */ lua_settable(L, 1); /* metatable.__newindex = array.set */ return 0; } 2288..55 LLiigghhtt UUsseerrddaattaa userdata full userdataLua userdata: light userdata light userdatum C void * lua_pushlightuserdata light userdatum void lua_pushlightuserdata (lua_State *L, void *p); userdatalight userdata full userdata Light userdata metatableslight userdata Programming in Lua 221 Copyright ® 2005, Translation Team, www.luachina.net light userdata full userdata light userdata light userdata full userdata Light userdata full userdata light userdata userdata Lua light userdata C Lua full userdata userdatum Lua userdata userdata, light userdata Lua full userdata light userdata userdata weak full userdata Programming in Lua 222 Copyright ® 2005, Translation Team, www.luachina.net 29 userdatum Lua Lua finalizer Lua __gc finalizers userdata userdatum usedatum __gc Lua userdatum userdatum API Lua ExpatExpat XML XML 2299..11 dir table dir entry for fname in dir(".") do print(fname) end C DIR opendir DIR closedir dir DIR dir DIR DIR userdatum userdatum __gc userdatumuserdatum Programming in Lua 223 Copyright ® 2005, Translation Team, www.luachina.net LuaDirLua upvalue 7Lua C dir Lua DIR upvalue __gc DIR metatable metatable dir #include #include /* forward declaration for the iterator function */ static int dir_iter (lua_State *L); static int l_dir (lua_State *L) { const char *path = luaL_checkstring(L, 1); /* create a userdatum to store a DIR address */ DIR **d = (DIR **)lua_newuserdata(L, sizeof(DIR *)); /* set its metatable */ luaL_getmetatable(L, "LuaBook.dir"); lua_setmetatable(L, -2); /* try to open the given directory */ *d = opendir(path); if (*d == NULL) /* error opening the directory? */ luaL_error(L, "cannot open %s: %s", path, strerror(errno)); /* creates and returns the iterator function (its sole upvalue, the directory userdatum, is already on the stack top */ lua_pushcclosure(L, dir_iter, 1); return 1; } 7 userdatum Programming in Lua 224 Copyright ® 2005, Translation Team, www.luachina.net userdatum lua_newuserdata DIR DIR userdatum __gc static int dir_iter (lua_State *L) { DIR *d = *(DIR **)lua_touserdata(L, lua_upvalueindex(1)); struct dirent *entry; if ((entry = readdir(d)) != NULL) { lua_pushstring(L, entry->d_name); return 1; } else return 0; /* no more values to return */ } __gc userdatum opendir userdatum opendir static int dir_gc (lua_State *L) { DIR *d = *(DIR **)lua_touserdata(L, 1); if (d) closedir(d); return 0; } int luaopen_dir (lua_State *L) { luaL_newmetatable(L, "LuaBook.dir"); /* set its __gc field */ lua_pushstring(L, "__gc"); lua_pushcfunction(L, dir_gc); lua_settable(L, -3); /* register the `dir' function */ lua_pushcfunction(L, l_dir); lua_setglobal(L, "dir"); return 0; } Programming in Lua 225 Copyright ® 2005, Translation Team, www.luachina.net dir_gc Lua metatable Lua 2299..22 XXMMLL xmllxp8LuaExpat http://www.libexpat.org/ ExpatCXML 1.0 SAXhttp://www.saxproject.org/ SAXXMLAPIAPI SAXXML Expat hi "hi" "hi" "end" Expat Lua Expat XML API Expat API Expat #include XML_Parser XML_ParserCreate (const char *encoding); void XML_ParserFree (XML_Parser p); NULL XML_SetElementHandler(XML_Parser p, XML_StartElementHandler start, XML_EndElementHandler end); XML_SetCharacterDataHandler(XML_Parser p, XML_CharacterDataHandler hndl); 8 lua xml parser Programming in Lua 226 Copyright ® 2005, Translation Team, www.luachina.net XML typedef void (*XML_StartElementHandler)(void *uData, const char *name, const char **atts); '\0' typedef void (*XML_EndElementHandler)(void *uData, const char *name) '\0' typedef void (*XML_CharacterDataHandler)(void *uData, const char *s, int len); Expat int XML_Parse (XML_Parser p, const char *s, int len, int isFinal); Expat XML_Parse XML_Parse isFinal XML 0 XML_Parse 0expat Expat void XML_SetUserData (XML_Parser p, void *uData); Lua Expat Lua Lua Lua local count = 0 callbacks = { Programming in Lua 227 Copyright ® 2005, Translation Team, www.luachina.net StartElement = function (parser, tagname) io.write("+ ", string.rep(" ", count), tagname, "\n") count = count + 1 end, EndElement = function (parser, tagname) count = count - 1 io.write("- ", string.rep(" ", count), tagname, "\n") end, } " " + to + yes - yes - to API API API p = lxp.new(callbacks) -- create new parser for l in io.lines() do -- iterate over input lines assert(p:parse(l)) -- parse the line assert(p:parse("\n")) -- add a newline end assert(p:parse()) -- finish document p:close() Lua userdatum userdata Expat Lua userdatum C userdatum 27.3.2 Lua registry Lua Expat Lua #include typedef struct lxp_userdata { Programming in Lua 228 Copyright ® 2005, Translation Team, www.luachina.net lua_State *L; XML_Parser *parser; /* associated expat parser */ int tableref; /* table with callbacks for this parser */ } lxp_userdata; static int lxp_make_parser (lua_State *L) { XML_Parser p; lxp_userdata *xpu; /* (1) create a parser object */ xpu = (lxp_userdata *)lua_newuserdata(L, sizeof(lxp_userdata)); /* pre-initialize it, in case of errors */ xpu->tableref = LUA_REFNIL; xpu->parser = NULL; /* set its metatable */ luaL_getmetatable(L, "Expat"); lua_setmetatable(L, -2); /* (2) create the Expat parser */ p = xpu->parser = XML_ParserCreate(NULL); if (!p) luaL_error(L, "XML_ParserCreate failed"); /* (3) create and store reference to callback table */ luaL_checktype(L, 1, LUA_TTABLE); lua_pushvalue(L, 1); /* put table on the stack top */ xpu->tableref = luaL_ref(L, LUA_REGISTRYINDEX); /* (4) configure Expat parser */ XML_SetUserData(p, xpu); XML_SetElementHandler(p, f_StartElement, f_EndElement); XML_SetCharacterDataHandler(p, f_CharData); return 1; } lxp_make_parser Programming in Lua 229 Copyright ® 2005, Translation Team, www.luachina.net userdatum consistent userdatum userdatum metatable __gc userdata Expat userdatum userdatum Expat userdatum C C Lua XML ( ) XML Expat static int lxp_parse (lua_State *L) { int status; size_t len; const char *s; lxp_userdata *xpu; /* get and check first argument (should be a parser) */ xpu = (lxp_userdata *)luaL_checkudata(L, 1, "Expat"); luaL_argcheck(L, xpu, 1, "expat parser expected"); /* get second argument (a string) */ s = luaL_optlstring(L, 2, NULL, &len); /* prepare environment for handlers: */ /* put callback table at stack index 3 */ lua_settop(L, 2); lua_getref(L, xpu->tableref); xpu->L = L; /* set Lua state */ /* call Expat to parse string */ status = XML_Parse(xpu->parser, s, (int)len, s == NULL); /* return error code */ lua_pushboolean(L, status); Programming in Lua 230 Copyright ® 2005, Translation Team, www.luachina.net return 1; } lxp_parse XML_Parse XML lxp_parse XML_Parse Expat s NULL true f_StartElement f_EndElement f_CharData callback Lua Lua f_CharData Lua parser static void f_CharData (void *ud, const char *s, int len) { lxp_userdata *xpu = (lxp_userdata *)ud; lua_State *L = xpu->L; /* get handler */ lua_pushstring(L, "CharacterData"); lua_gettable(L, 3); if (lua_isnil(L, -1)) { /* no handler? */ lua_pop(L, 1); return; } lua_pushvalue(L, 1); /* push the parser (`self') */ lua_pushlstring(L, s, len); /* push Char data */ lua_call(L, 2, 0); /* call the handler */ } XML_SetUserData C lxp_userdata lxp_parse callback 3 parser 1parser lxp_parse f_EndElement f_CharData Lua parser '\0' static void f_EndElement (void *ud, const char *name) { lxp_userdata *xpu = (lxp_userdata *)ud; lua_State *L = xpu->L; Programming in Lua 231 Copyright ® 2005, Translation Team, www.luachina.net lua_pushstring(L, "EndElement"); lua_gettable(L, 3); if (lua_isnil(L, -1)) { /* no handler? */ lua_pop(L, 1); return; } lua_pushvalue(L, 1); /* push the parser (`self') */ lua_pushstring(L, name); /* push tag name */ lua_call(L, 2, 0); /* call the handler */ } f_StartElement parser Lua { method = "post", priority = "high" } f_StartElement static void f_StartElement (void *ud, const char *name, const char **atts) { lxp_userdata *xpu = (lxp_userdata *)ud; lua_State *L = xpu->L; lua_pushstring(L, "StartElement"); lua_gettable(L, 3); if (lua_isnil(L, -1)) { /* no handler? */ lua_pop(L, 1); return; } lua_pushvalue(L, 1); /* push the parser (`self') */ lua_pushstring(L, name); /* push tag name */ /* create and fill the attribute table */ lua_newtable(L); while (*atts) { Programming in Lua 232 Copyright ® 2005, Translation Team, www.luachina.net lua_pushstring(L, *atts++); lua_pushstring(L, *atts++); lua_settable(L, -3); } lua_call(L, 3, 0); /* call the handler */ } close Expat callback static int lxp_close (lua_State *L) { lxp_userdata *xpu; xpu = (lxp_userdata *)luaL_checkudata(L, 1, "Expat"); luaL_argcheck(L, xpu, 1, "expat parser expected"); /* free (unref) callback table */ luaL_unref(L, LUA_REGISTRYINDEX, xpu->tableref); xpu->tableref = LUA_REFNIL; /* free Expat parser (if there is one) */ if (xpu->parser) XML_ParserFree(xpu->parser); xpu->parser = NULL; return 0; } consistent, 28.3 metatable__index static const struct luaL_reg lxp_meths[] = { {"parse", lxp_parse}, {"close", lxp_close}, {"__gc", lxp_close}, {NULL, NULL} Programming in Lua 233 Copyright ® 2005, Translation Team, www.luachina.net }; OO static const struct luaL_reg lxp_funcs[] = { {"new", lxp_make_parser}, {NULL, NULL} }; open metatable__index int luaopen_lxp (lua_State *L) { /* create metatable */ luaL_newmetatable(L, pat"); "Ex /* metatable.__index = metatable */ lua_pushliteral(L, "__index"); lua_pushvalue(L, -2); lua_rawset(L, -3); /* register methods */ xp_meths, 0); luaL_openlib (L, NULL, l /* register functions (only lxp.new) */ luaL_openlib (L, "lxp", lxp_funcs, 0); return 1; }
  • 还剩242页未读

    继续阅读

    下载pdf到电脑,查找使用更方便

    pdf的实际排版效果,会与网站的显示效果略有不同!!

    需要 10 金币 [ 分享pdf获得金币 ] 1 人已下载

    下载pdf

    pdf贡献者

    fkby1993

    贡献于2016-02-29

    下载需要 10 金币 [金币充值 ]
    亲,您也可以通过 分享原创pdf 来获得金币奖励!
    下载pdf