 
來源: programming-in-lua-2ed.pdf
更新記錄
| item | note | 
|---|---|
| 20160817 | 第一版 | 
目錄
- Chapter 1
- Types and Values
- String
- Table
- Chapter 3 Expressions
- Chapter 4 Statement
- 4-3 Control Structures
- Chapter5 Function
- Chapter 6 -More About Function
- Chapter7 Iterator and the Generic for
- Chapter8 Compilation,Excution,and Errors
- Chapter9 Coroutines (協同程序)
- Chapter 11 Data Structures
- PARTIII; The Standard Library (待增加)
- PARTIV; The C API (待增加)
- 其它
- 參考來源
Chapter 1
Chunks
- Each piece of code that Lua executes, such as a file or a single line in interac-tive mode, is called a chunk.
- A chunk is simply a sequence of commands (or statements).
- 單行的程式
 可以使用分號(semicolon)也可以不使用分號1 
 2
 3
 4
 5
 6a = 1 
 b = a*2
 a = 1;
 b = a*2;
 a = 1; b = a*2
 a = 1 b = a*2 -- ugly, but valid
Some Lexical Conventions (词法约定)
- 變數定義不可以使用數字開頭
- 變數定義可以使用低線(_)開頭1 
 2i j i10 _ij 
 aSomewhatLongName _INPUT
Global Variables
- 預設定義為全域變數
- 沒有定義的變數使用時將會回傳nil1 
 2
 3print(b) --> nil 
 b = 10
 print(b) --> 10
Types and Values
basic types
eight basic types in Lua:
- nil : 表示未初始化的變數
 變數若設定為nil,即為刪除變數
- boolean :  false or true
 只有false及nil會回傳false, 其它為true
- number : 數字
 ex. 4 0.4 4.57e-3 0.3e12 5e+20
- string : 字串
- userdata,
- function
- thread
- table. - 1 
 2
 3
 4
 5
 6
 7- 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
- type(x)回傳為字串 
String
- Strings in Lua are immutable values
 表示不能去修改字串內容,需要產生一個新的字串內容以符合需求1 
 2
 3
 4a = "one string" 
 b = string.gsub(a, "one", "another") -- change string parts
 print(a) --> one string
 print(b) --> another string
使用 [[ 及 ]] 定義多行字串內容
- 使用 [[ 及 ]] 定義多行字串內容1 
 2
 3
 4
 5
 6
 7
 8
 9
 10page = [[ 
 <html>
 <head>
 <title>An HTML Page</title>
 </head>
 <body>
 <a href="http://www.lua.org">Lu
 </body>
 </html>
 ]]
concatenation operator(連接運算符號)
- The .. is the string concatenation operator in Lua1 print(10 .. 20) --> 1020 
取得字串長度
- In Lua 5.1, you can get the length of a string using the  operator `#’1 
 2
 3
 4
 5
 6
 7a = "hello" 
 print(#a) --> 5
 print(#"good\0bye") --> 8
 for i=1, #a do
 print(a[i])
 end
Table
- table { } 實現一個array,此array可以存放number,string或其它,但不可以是nil - 1 
 2
 3
 4
 5
 6
 7
 8
 9- a = {} -- create a table and store its reference in 'a' 
 k = "x"
 a[k] = 10 -- new entry, with key="x" and value=10
 a[20] = "great" -- new entry, with key=20 and value="great"
 print(a["x"]) --> 10
 k = 20
 print(a[k]) --> "great"
 a["x"] = a["x"] + 1 -- increments entry "x"
 print(a["x"]) --> 11
- providing a.name as syntactic sugar for a[“name”] - 1 
 2
 3- a.x = 10 -- same as a["x"] = 10 
 print(a.x) -- same as print(a["x"])
 print(a.y) -- same as print(a["y"])
Chapter 3 Expressions
優先順序
| seq | item | 
|---|---|
| 1 | ^ | 
| 2 | not # - (unary) | 
| 3 | * / % | 
| 4 | + - | 
| 5 | .. | 
| 6 | < > <= >= ~= == | 
| 7 | and | 
| 8 | or | 
- ex1 
 2
 3
 4
 5a+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)
3.6 Table Constructors
- ex1 - 1 - a = {x=10, y=20} 
- This previous line is equivalent to these commands: - 1 - a = {}; a.x=10; a.y=20 
- We can mix record-style and list-style initializations in the same constructor: - 1 
 2
 3
 4
 5
 6- polyline = {color="blue", thickness=2, npoints=4, 
 {x=0, y=0},
 {x=-10, y=0},
 {x=-10, y=1},
 {x=0, y=1}
 }
- Each of the elements polyline[i] is a table representing a record: - 1 
 2- print(polyline[2].x) --> -10 
 print(polyline[4].y) --> 1
Chapter 4 Statement
4-1 Assignment
- Assignment is the basic means of changing the value 
 a = “hello” .. “world”
 multiple assignment- 1 
 2
 3- a, b = 10, 2*x 
 x, y = y, x -- swap 'x' for 'y'
 a[i], a[j] = a[j], a[i] -- swap 'a[i]' for 'a[j]'
- 無相對應到的變數,將會設定為nil(即除刪) - 1 
 2- a, b, c = 0, 1 
 print(a, b, c) --> 0 1 nil
4-2 Local Variables and Blocks
- Besides global variables, Lua supports local variables - 1 
 2- j = 10 -- global variable 
 local i = 1 -- local variable
- Unlike global variables, local variables have their scope limited to the block 
- It is good programming style to use local variables whenever possible
 Local variables help you avoid cluttering the global environment with unnecessary names.1 
 2
 3
 4
 5
 6
 7local a, b = 1, 10 
 if a < b then
 print(a) --> 1
 local a -- '= nil' is implicit
 print(a) --> nil
 end -- ends the block started at 'then'
 print(a, b) --> 1 10
4-3 Control Structures
- if,while,repeat,for 等需要end表示結束(terminates)
- Lua treats as true all values different from false and nil
if then else
- ex1 - 1 
 2
 3
 4
 5
 6- if a < 0 then a = 0 end 
 if a < b then return a else return b end
 if line > MAXLINES then
 showpage()
 line = 0
 end
- ex2 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11- if op == "+" then 
 r = a + b
 elseif op == "-" then
 r = a - b
 elseif op == "*" then
 r = a*b
 elseif op == "/" then
 r = a/b
 else
 error("invalid operation")
 end
The for statement
- 由exp1到exp2, 每次增加exp3(若無exp3則預設值為1) - 1 
 2
 3- for var=exp1,exp2,exp3 do 
 <something>
 end
- ex. - 1 
 2- for i=1,f(x) do print(i) end 
 for i=10,1,-1 do print(i) end
- If you want to end a for loop before its normal termination, use break 
- The generic for loop traverses all values returned by an iterator function:1 
 2-- print all values of array 'a' 
 for i,v in ipairs(a) do print(v) end
4-4 break and return
- The break and return statements allow us to jump out of a block.
- This statement breaks the inner loop (for, repeat, or while) that contains it1 
 2
 3
 4
 5local i = 1 
 while a[i] do
 if a[i] == v then break end
 i = i + 1
 end
Chapter5 Function
function
- function定義方式1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14a={[1]=11,[2]=12,[3]=10} 
 
 function add (a)
 local sum = 0
 for i,v in ipairs(a) do
 sum = sum + v
 end
 return sum
 end
 
 print(add(a))
 xx :[/tmp/tt]# lua t1.lua
 33
function parameter
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) | 
如何設定給函數預設參數值
- 未給預參數值n, 則此時為nil
- 當未代入參數,則設定預設值n為11 
 2
 3
 4function incCount (n) 
 n = n or 1
 count = count + n
 end
Chapter 6 -More About Function
Lua為First Class Value
指任何程式中的實體(ex. function,object,..)
即表示:function可以被當成參數傳遞或回傳
絕大多數語言中,數值與基礎型別都是第一類物件,然而不同語言中對函數的區別很大
- C語言與C++中的函數不是第一類物件,因為在這些語言中函數不能在執行期創造,而必須在設計時全部寫好
- Scheme中的函數是第一類物件,因為可以用lambda語句來創造匿名函數並作為第一類物件來操作
Closure(閉合函數)
將函數寫在另一個函數裡面,內部函數可以取得外部變數中的區域變數
- 範例內容 
 c1及c2是同一個函數創建兩個不同的Closure
 個自擁有區域變數i- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16- function newCounter() 
 local i = 0
 return function ()
 i = i + 1
 return i
 end
 end
 c1 = newCounter()
 print(c1())
 print(c1())
 c2 = newCounter()
 print(c2())
 print(c1())
 print(c2())
- 執行結果 - 1 
 2
 3
 4
 5
 6- gk350a :[/tmp/tt]# lua t2.lua 
 1
 2
 1
 3
 2
非全域的函數(non-global function)
- When we store a function into a local variable, we get a local function
- 此local function會被限制在某些做用區使用
- package can use these local functions: - 1 
 2
 3- local f = function(<param>) 
 <body>
 end
- 正確方式 - 1 
 2
 3
 4
 5
 6
 7
 8- local fact 
 fact = function (n)
 if n == 0 then return 1
 else return n*fact(n-1)
 end
 end
 print(fact(3))
- 錯誤的方式 
 在recursive funtion時,lua變數需要提前宣告
 在fact(n-1)時fact尚未定義,看來lua是無js的variable hositing方式- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14- local fact = function (n) 
 if n == 0 then return 1
 else return n*fact(n-1)
 end
 end
 print(fact(3))
 # lua local-fu.lua
 lua: local-fu.lua:3: attempt to call global 'fact' (a nil value)
 stack traceback:
 local-fu.lua:3: in function 'fact'
 local-fu.lua:7: in main chunk
 [C]: ?
- 此方式的寫法在node js是沒問題,看來lua及node js還有些不同 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15- $ cat local-t1.js 
 var fact = function (n) {
 if(n == 0){
 return 1;
 } else {
 return n*fact(n-1);
 }
 }
 console.log("tt");
 console.log(fact(3));
 $ node local-t1.js
 tt
 6
提前宣告
在indirect recursive funtion時,lua變數需要提前宣告
| 1 | local f,g -- ' forwared decalartions' | 
函數允許多個回傳值(5-1 Multiple Results)
- 定義 - 1 
 2
 3- function foo0 () end -- returns no results 
 function foo1 () return "a" end -- returns 1 result
 function foo2 () return "a","b" end -- returns 2 results
- 用法 - 1 
 2
 3- x,y = foo2() -- x="a", y="b" 
 x = foo2() -- x="a", "b" is discar
 x,y,z = 10,foo2() -- x=10, y="a", z="b"
Proper Tail Calls
- Lua does tail-call elimination 
- Tail Calls 模式 
 在撰寫遞迴時,每次的遞迴呼叫都會導致新的Stack frame產生,導致整個呼叫所編譯出來的Call Stack過大
 Tail Call算是一種演算法,指的是在該子程式的尾端再進行遞迴呼叫
 目的是希望藉此不必再額外產生新的Stack frame;不過必非所有的程式語言都有支援這樣特性
 出處:初探ECMAScript 6- 1 
 2
 3
 4
 5
 6
 7
 8- //es6 
 function fact(n,acc=1){
 if (n <=1) return acc;
 return factorial(n-1,n*acc);
 }
 console.log(fact(10000));
- 範例 
 房間移動範例,目前有4間如下
 使用tail calls寫法,讓程式更簡單- 1 
 2
 3- | room1 | room2 | 
 -------------------------
 | room3 | room4 |
- 範例程式 
 xx :[~]# cat room.lua- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39- function room1() 
 print("entry room1")
 local move = io.read()
 if move == "south" then return room3()
 elseif move == "east" then return room2()
 else
 print("invaild move")
 return room1()
 end
 end
 function room2()
 print("entry room2")
 local move = io.read()
 if move == "south" then return room4()
 elseif move == "west" then return room1()
 else
 print("invaild move")
 return room2()
 end
 end
 function room3()
 print("entry room3")
 local move = io.read()
 if move == "north" then return room1()
 elseif move == "east" then return room4()
 else
 print("invaild move")
 return room3()
 end
 end
 function room4()
 print("entry room4")
 print ("congratulations!");
 end
 room1()
- 測試 
 :[~]# lua room.lua- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16- entry room1 
 north
 invaild move
 entry room1
 sorth
 invaild move
 entry room1
 south
 entry room3
 north
 entry room1
 east
 entry room2
 south
 entry room4
 congratulations!
Chapter7 Iterator and the Generic for
如何使用Closure建立itera
- iter = values(t) 
 此時建立Closure函數 (好處,不會響影其它的變數)
 回傳nil則表示結束
 $ cat chapter7-for.lua- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17- function values (t) 
 local i = 0
 return function () i = i + 1; return t[i] end
 end
 t = {10, 20, 30}
 iter = values(t)
 print(iter())
 print(iter())
 print(iter())
 print(iter())
 xx :[~]# lua chapter7-for.lua
 10
 20
 30
 nil
- iterator: 與while一起使用 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13- function values (t) 
 local i = 0
 return function () i = i + 1; return t[i] end
 end
 t = {10, 20, 30}
 iter = values(t)
 while true do
 local element = iter()
 if element == nil then break end
 print(element)
 end
- xx :[~]# lua chapter7-while.lua - 1 
 2
 3- 10 
 20
 30
- iterator: 與for一起使用 
 用更少變數,程式變更簡單 (不需要iter變數)
 The generate for does all the bookkeeping for an iteration loop
 it keeps the iterator function interanlly, so we do not need the itera variable
 $ cat chapter7-for-t1.lua- 1 
 2
 3
 4
 5
 6
 7
 8
 9- function values (t) 
 local i = 0
 return function () i = i + 1; return t[i] end
 end
 t = {10, 20, 30}
 for element in values(t) do
 print(element)
 end
- xx :[~]# lua chapter7-for-t1.lua - 1 
 2
 3- 10 
 20
 30
- 將目前輸入的單子找出來(只允語數字及字母), 且回傳每個找到的單字 
 使用itera closure方式,將整個功能獨立分開(不會影響主程式變數)
 $ cat chapter7-words.lua- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24- function allwords() 
 local line = io.read()
 print('<1>line:',line) -- debug print
 local pos = 1
 return function ()
 print('<2>line:',line,' ,pos:',pos) -- debug print
 while line do
 local s, e = string.find(line,"%w+", pos) -- string.find: 會回找到的s,e
 if s then
 pos = e + 1
 return string.sub(line, s, e)
 else
 line = io.read()
 print('<3>line:',line) -- debug print
 pos = 1
 end
 end
 return nil
 end
 end
 for word in allwords() do
 print(word)
 end
- xx :[~]# lua chapter7-words.lua 
 string.find: 會回找到的s,e
 pattern %w: represents all alphanumeric characters.
 5.4.1 – Patterns- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23- t11 t22 t33 
 <1>line: t11 t22 t33
 <2>line: t11 t22 t33 ,pos: 1
 t11
 <2>line: t11 t22 t33 ,pos: 4
 t22
 <2>line: t11 t22 t33 ,pos: 8
 t33
 <2>line: t11 t22 t33 ,pos: 12
 taa tbb tcc
 <3>line: taa tbb tcc
 taa
 <2>line: taa tbb tcc ,pos: 4
 tbb
 <2>line: taa tbb tcc ,pos: 8
 tcc
 <2>line: taa tbb tcc ,pos: 12
 ##!!@@aa%%^^ ^^&& **((11
 <3>line: ##!!@@aa%%^^ ^^&& **((11
 aa
 <2>line: ##!!@@aa%%^^ ^^&& **((11 ,pos: 9
 11
 <2>line: ##!!@@aa%%^^ ^^&& **((11 ,pos: 25
Chapter 7-2 The Semantics of the Generic for
- lua內部for語法動作程序
- use the generic for itself to keep the iteration state
- In this section we will see the facilities that the generic for offers to hold state
- The syntax for the generic for is as follows - 1 
 2
 3- for <var-list> in <exp-list> 
 <body>
 end
- for實際範例 - 1 - for k,v in piars(t) do print(k,v) end 
- for內部會保存3個變數 - iterator function ( _f )
- invariant state ( _s )
- a control variable( _var )
 
- More precisely, a construction like - 1 - for var_1,...,var_n in <explist> do <block> end 
- is equivalen to the following code: 
 實際程序如下,內部會保存3個變數(_f,_s,_var)- 需要回傳(_f,_s,_var) 
 此時以for而言內部只允了,儲存1狀態變數
 (若_f裡面需要由外部帶入,兩個以上的變數,要如何做?)- 1 
 2
 3
 4
 5
 6
 7
 8- 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
 end
 end
Chapter 7-3 無需儲存狀態的iterator (Stateless Iterators)
表示自身不保存任可狀態的選代器(iterator)
- $cat chapter7-3-ipairs.lua - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15- local function iter (a,i) 
 i = i + 1
 local v = a[i]
 if v then
 return i,v
 end
 end
 function myipairs(a)
 return iter, a, 0
 end
 a = {"one", "two", "three"}
 for i,v in myipairs(a) do
 print(i,v)
 end
- xx :[~]# lua chapter7-3-ipairs.lua - 1 
 2
 3- 1 one 
 2 two
 3 three
Chapter 7-4 Iterators with Complex State
- 通常,Iteration需要保存許多狀態,但for只提供1個(invariant state)及1個控制變量(a control variable)用於狀態的保存
- 解決方式 - 1.使用clousre
- 2.或是將所有狀態打包為1個table,保存在(invariant state) -> 為此節要示範的例
 
- $ cat chapter7-4-itra.lua - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24- local iterator 
 function allword()
 local state = {line = io.read(), pos = 1}
 return iterator, state
 end
 function iterator (state)
 while state.line do
 local s, e = string.find(state.line, "%w+", state.pos)
 if s then
 state.pos = e + 1
 return string.sub(state.line, s, e)
 else
 state.line = io.read()
 state.pos = 1
 end
 end
 return nil
 end
 for word in allword() do
 print(word)
 end
- xx:[~]# lua chapter7-4-itra.lua - 1 
 2
 3
 4- t11 t22 t33 
 t11
 t22
 t33
Chapter 7-5 True Iterators (allword iterator)
- $ cat chapter7-5-allword.lua - 1 
 2
 3
 4
 5
 6
 7
 8- function allwords(f) 
 for line in io.lines() do
 for word in string.gmatch(line, "%w+") do
 f(word)
 end
 end
 end
 allwords(print)
- xx :[~]# lua chapter7-5-allword.lua - 1 
 2
 3
 4- t11 t22 t33 
 t11
 t22
 t33
使用匿名函數做為參數輸入
- $ cat chapter7-5-allword-t2.lua - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- function allwords(f) 
 line = io.read()
 for word in string.gmatch(line, "%w+") do
 f(word)
 end
 end
 local count = 0
 allwords(function (w)
 if w == "hello" then count = count +1 end
 end)
 print(count)
- xx :[~]# lua chapter7-5-allword-t2.lua - 1 
 2- t11 hello t22 hello t33 
 2
Chapter8 Compilation,Excution,and Errors
Lua允語由外部載入precompiles source code(ex. dofile )
Chapter8-1 Compilation
- dofile as a kind of primitive operation to run chunks of Lua code
- dofile is actually an auxiliary function- loadfile does the hard work
- loadfile loads a Lua chunk from a file, but it does not run the chunk
 
- loadfile只是將代碼編譯,但不會執行,並且回傳一個函數返回
- loadfile不會引發錯誤(它是返回錯誤並不處理錯誤)
- dofile可以看成下例功能 - 1 
 2
 3
 4- function dofile (filename) 
 local f = assert (loadfile(filename))
 return f()
 end
- dofile ([filename]) 
 Opens the named file and executes its contents as a Lua chunk.
- load (func [, chunkname]) 
 Loads a chunk using function func to get its pieces.
- loadfile ([filename]) 
 Similar to load, but gets the chunk from file filename or from the standard input, if no file name is given.
loadfile example
- loadfile(“foo.lua”) 
 之後,函數foo完成編譯,但還沒定義
- f() 
 定義此foo function
- $ cat foo.lua - 1 
 2
 3- function foo (x) 
 print(x)
 end
- $ cat chapter8-2-loadfile.lua - 1 
 2
 3
 4
 5- f = loadfile("foo.lua") 
 print(foo)
 f()
 print(foo)
 foo("ok")
- gk350a :[~]# lua chapter8-2-loadfile.lua - 1 
 2
 3- nil 
 function: 0xd6bcc0
 ok
Chapter8.2 Code (如何載入C定義的lua library )
- package.loadlib (libname, funcname) 
 Dynamically links the host program with the C library libname.
 funcname must follow the protocol (see lua_CFunction)
- $ cat chapter8-2-loadlib.lua - 1 
 2- local path = "/usr/local/lib/lua/5.1/socket/core.so" 
 local f = package.loadlib(path,"luaopen_socket")
Chapter8.3 Error (如何取得程式的錯誤訊息)
通過error()函數傳入錯誤訊息
- 
- Terminates the last protected function called and returns message as the error message. Function error never returns.
- Usually, error adds some information about the error position at the beginning of the message
- With level 1 (the default), the error position is where the error function was called
- Level 2 points the error to where the function that called error was called
 
- $ cat chapter8-3-err.lua - 1 
 2
 3- print "enter a number:" 
 n = io.read("*number")
 if not n then error("invaild input") end
- xx :[~]# lua chapter8-3-err.lua - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- enter a number: 
 dd
 lua: chapter8-3-err.lua:3: invaild input
 stack traceback:
 [C]: in function 'error'
 chapter8-3-err.lua:3: in main chunk
 [C]: ?
 gk350a :[~]# lua chapter8-3-err.lua
 enter a number:
 10
使用assert()功能來實現
- assert (v [, message]) 
 Issues an error when the value of its argument v is false (i.e., nil or false); otherwise, returns all its arguments.
 message is an error message; when absent, it defaults to “assertion failed!”
- $ cat chapter8-3-err2.lua - 1 
 2- print "enter a number:" 
 n = assert(io.read("*nubmer"),"invaild input")
Chapter8-4 Error Handling and Exceptions
若需要lua中處理錯誤,則必需使用pcall函數來包裝要執行的代碼
- pcall (f, arg1, ···) 
 Calls function f with the given arguments in protected mode.
- $ cat chapter8-4-pcall.lua - 1 
 2
 3
 4
 5- cat chapter8-4-pcall.lua 
 local status,err = pcall(function () error({code=121}) end)
 print(status,err.code)
 local status,err = pcall(function () error("my error") end)
 print(status,err)
- gk350a :[~]# lua chapter8-4-pcall.lua - 1 
 2- false 121 
 false chapter8-4-pcall.lua:3: my error
Chapter9 Coroutines (協同程序)
- A coroutine is similar to a thread (in the sense of multithreading)- it is a line of execution, with its own stack, its own local variables, and its own instruction pointer;
- but sharing global variables and mostly anything else with other coroutines
 
- 多thead,是指同時多個程序一起跑
- 但coroutine,主要強調在多個thead中如何協同處理
Coroutine Manipulation
- 2.11 – Coroutines- Lua supports coroutines, also called collaborative multithreading.
- A coroutine in Lua represents an independent thread of execution
 
| func | note | 
|---|---|
| coroutine.create | create a coroutine , it does not start the coroutine execution. | 
| coroutine.resume | passing as its first argument a thread, the coroutine starts its execution | 
- A coroutine can terminate its execution in two ways: 
 normally, when its main function returns (coroutine.resume returns true)
 and abnormally
- 5.2 – Coroutine Manipulation 
 The operations related to coroutines comprise a sub-library of the basic library and come inside the table coroutine.
- coroutine有下例狀態 - suspended
 coroutine.create之後則為suspened
- running
 coroutine.resume之後則為running,若程式跳完離開則變成dead
- dead
- normal
 
- suspended
- coroutine.yield()會讓一個運行中的coroutine變成suspended狀態(即此時,程式停止) 
- $cat chapter9-yield.lua - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16- co = coroutine.create(function () 
 for i=1,5 do
 print("co",i)
 coroutine.yield()
 end
 end)
 coroutine.resume(co)
 print("t1",coroutine.status(co))
 coroutine.resume(co)
 coroutine.resume(co)
 coroutine.resume(co)
 coroutine.resume(co)
 coroutine.resume(co)
 print("t2",coroutine.status(co))
 coroutine.resume(co)
- xx:[~]# lua chapter9-yield.lua - 1 
 2
 3
 4
 5
 6
 7- co 1 
 t1 suspended
 co 2
 co 3
 co 4
 co 5
 t2 dead
通過resume-yield交換數據
- $cat chapter9-2-data.lua - 1 
 2
 3
 4
 5
 6- co = coroutine.create( function (a,b,c) 
 print("co",a,b,c)
 coroutine.yield(a+10,b+10,c+10)
 end)
 print(coroutine.resume(co,1,2,3))
- xx:[~]# lua chapter9-2-data.lua - 1 
 2- co 1 2 3 
 true 11 12 13
chapter9-2 producer-consumer problem
- 由coroutine.yield(x)回傳值x
- 此處為consumer-driver design- 由consumer啟動
- 當consumber需要新值時,喚醒producer
- producer產生1個新的值,停止運行,等待consumer
 
- $ cat chapter9-2-pipe.lua - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22- local producer 
 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()
 send(x)
 end
 end
 )
 print(receive())
- xx:[~]# lua chapter9-2-pipe.lua - 1 
 2- test 
 test
chapter 9-2 filter
- filter example- 由filter來處理過程的資料
- 決定是否打用producer資料
- 是否將傳給consumer資料做格式轉換
 
 
- $cat chapter9-2-filter.lua - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39- function receive (prod) 
 local status, value = coroutine.resume(prod)
 return value
 end
 function send(x)
 coroutine.yield(x)
 end
 function producer(x)
 return coroutine.create(function ()
 while true do
 print("producer:")
 local x = io.read()
 send(x)
 end
 end)
 end
 function filter (prod)
 return coroutine.create( function()
 for line = 1, math.huge do
 local x = receive (prod)
 x = string.format("filter: %5d %s",line,x)
 send(x)
 end
 end)
 end
 function consumer (prod)
 while true do
 local x = receive(prod)
 io.write("cosumer:",x,"\n");
 end
 end
 p = producer()
 f = filter(p)
 consumer(f)
- xxx :[~]# lua chapter9-2-filter.lua - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- producer: 
 test11
 cosumer:filter: 1 test11
 producer:
 aabb
 cosumer:filter: 2 aabb
 producer:
 ccdd
 cosumer:filter: 3 ccdd
 producer:
Chapter 11 Data Structures
- all structure that other language offer- arrays, records, lists, queues, sets
 
Chapter 11-1 Arrays
- 注意lua內部library的array皆為1開始 
- $cat chapter11-1-array.lua - 1 
 2
 3
 4
 5- a = {} 
 for j=1, 1000 do
 a[j] = 0
 end
 print(#a)
- gk350a :[~]# lua chapter11-1-array.lua - 1 - 1000 
- 也可以建立非零開始的index 
- $cat chapter11-1-array2.lua 1 
 2
 3
 4a = {} 
 for i=-5, 5 do
 a[i] = 0
 end
Chapter 11-2 matrix(矩陣)
- $cat chapter11-2-matrix.lua - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- mt = {} 
 N = 3
 M = 4
 for i=1,N do
 mt [i] = {}
 for j=1,M do
 mt[i][j] = 0
 end
 end
 print(#mt)
 print(#mt[1])
- xx :[~]# lua chapter11-2-matrix.lua - 1 
 2- 3 
 4
Chapter 11-4 Queues
- 由List.New初始化變數
 first: 指向list頭
 last: 指向list尾
- pushfist: 由first新增
- popfist: 由first取出
- pushlast: 由last新增
- poplast: 由last取出
- $cat chapter11-4-queues.lua - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34- List = {} 
 function List.new ()
 return {first = 0, last = -1}
 end
 function List.pushfirst(list, value)
 local first = list.first - 1
 list.first = first
 list[first] = value
 end
 function List.pushlast (list, value)
 local last = list.last + 1
 list.last = last
 list[last] = value
 end
 function List.popfirst (list)
 local first = list.first
 if first > list.last then error ("list is empty") end
 local value = list[first]
 list[first]=nil
 list.first = first +1
 return value
 end
 function List.poplast (list)
 local last = list.last
 if list.first > last then error("list is empty") end
 local value = list[last]
 list[last] = nil
 list.last = last -1
 return value
 end
- test code - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17- tt = {} 
 tt = List.new()
 print(tt.first,tt.last)
 List.pushfirst(tt,"11")
 print("pushfirst 11",tt.first,tt.last)
 List.pushfirst(tt,"21")
 print("pushfirst 21",tt.first,tt.last)
 List.pushfirst(tt,"31")
 print("pushfirst 31",tt.first,tt.last)
 print(tt[-1],tt[-2],tt[-3])
 print(tt[-2])
 print(tt[-3])
 print("poplast value:",List.poplast(tt))
 print("poplast",tt.first,tt.last)
 print(tt[-1],tt[-2],tt[-3])
 print(tt[-2])
 print(tt[-3])
- xx:[~]# lua chapter11-4-queues.lua - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- 0 -1 
 pushfirst 11 -1 -1
 pushfirst 21 -2 -1
 pushfirst 31 -3 -1
 11 21 31
 21
 31
 poplast value: 11
 poplast -3 -2
 nil 21 31
 21
 31
PARTIII; The Standard Library (待增加)
PARTIV; The C API (待增加)
其它
pairs及ipairs差異
- pairs:依table內的順序一個一個找出來 
 會找到全部- 1 
 2
 3
 4
 5
 6
 7
 8
 9- a={[1]=11,[2]=22,[5]=55,["erwin"]=90, ["peter"]=92} 
 for i,v in pairs(a) do print(i,v) end
 xx :[/tmp/tt]# lua t1.lua
 2 22
 1 11
 p 92
 5 55
 e 90
- ipairs 
 pairs進階的找法,只依1,2,依順找,當沒有找到則離開- 1 
 2
 3
 4
 5
 6
 7- a={[1]=11,[2]=22,[5]=55,["erwin"]=90, ["peter"]=92} 
 for i,v in ipairs(a) do print(i,v) end
 xx :[/tmp/tt]# lua t1.lua
 1 11
 2 22