SlideShare a Scribd company logo
Lua腳本語言
Revised on October 15, 2020
 Lua腳本語言
 資料型別
 變數Scope
 Functions
 運算子
 流程控制
 Table
 Meta table
 內建函式
 檔案作業
 使用模組
 OOP
 Windows安裝Lua系統
 使用Visual Studio Code開發Lua程式
 Lua是⼀種簡潔,輕量、可延伸的可嵌入腳本語言
 Lua虛擬機和解釋譯都是C編寫
 Lua核心體積小、啟動速度快,很容易嵌入其它語言中使用
 Lua易於學習,只有21個關鍵字,Lua語法類似於英語,也易於閱讀和
理解
Lua語言簡介
2
 下載Lua Windows x64 Executables壓縮檔
 http://luabinaries.sourceforge.net/download.html
 在C:Program Files下建立Lua目錄
 解壓縮lua-5.4.0_Win64_bin.zip,將lua54.dll, lua54.exe,
luac54.exe及wlua54.exe複製到Lua目錄
 將lua54.exe更名為lua.exe
 將C:Program FilesLua加入到PATH環境變數
Windows安裝Lua系統 1/2
3
 開啟命令列視窗,輸入lua -v
Windows安裝Lua系統 2/2
4
 hello.lua
print ('hello, world')
測試Lua程式
5
 下載
 http://code.visualstudio.com/
 新增檔案
 變更文件語言樣式
 點擊右下角「純文字」標籤,選從下拉單中選擇Lua
使用Visual Studio Code開發Lua程式 1/5
6
使用Visual Studio Code開發Lua程式 2/5
7
 編輯程式碼並存檔
使用Visual Studio Code開發Lua程式 3/5
8
 安裝Lua Debug延伸模組
使用Visual Studio Code開發Lua程式 4/5
9
 執行測試Lua程式
使用Visual Studio Code開發Lua程式 5/5
10
執行結果
 要建立變數,您需要做兩件事:
 宣告變數名稱
 為變數指定⼀個值(數據)
 例如:
foo = 'bar'
 Lua是採用動態型別,程式在直譯時才會根據變數值,宣告成適當的
資料型別
變數
11
 --之後到該行結束都會視為註解文字
foo = 'bar'
print (foo)
-- The above statement never prints
-- because it is commented out.
程式註解
12
 Lua支援8種基本資料型別
 nil
欠缺資料。用來表示資料無效或不存在
 Boolean
資料值只能為true或false
 number
實數值
 string
字串資料為⼀種字元陣列,資料前後必須加引號
 function
函數是使用名稱來引用的某些程式碼,並可隨時執行
基本資料型別 1/2
13
 table
表格使用「鍵-值」來儲存訊息
 userdata
使用C語言定義的複雜資料結構
 thread
執行緒可用於並行執行程式,它可以同時運行多組命令
基本資料型別 2/2
14
 nil表示沒有資料。如果您嘗試取用⼀個尚未創建的變數,則其值為
nil
 當變數已不再使用,應將其值設為nil
print (foo) -- will print: nil
foo = 'bar'
print (foo) -- will print: bar
foo = nil
print (foo) -- will print: nil
nil
15
 布林變數只具有兩個值之⼀:true或false
 布林通常用於程式流程控制及邏輯敘述
foo = true
print ('The value of foo is:')
print (foo) -- will print: true
result = 5 > 3
print ('Is 5 > 3?')
print (result) -- will print: true
Boolean
16
 Lua的所有數字都是實數,不會區分整數和小數
 如果只需要整數,可使用內置函數math.floor無條件捨去或
math.ceil無條件進位
pi = 3.1415
three = math.floor(3.1415)
five = math.ceil(4.145)
print (pi) -- will print: 3.1415
print (three) -- will print: 3
print (five) -- will print: 5
five = 3 + 2
print (five) -- will print 5
print (2 + 2) -- will print 4
print (five + 1) -- will print 6
print (pi + 1) -- will print 4.1415
number
17
 type函式會以字串形式回傳變數的型別
var1 = true
var2 = 3.145
var4 = type(var1)
var5 = type(type(var2))
print (type(var1)) -- boolean
print (type(var2)) -- number
print (type(var3)) -- nil
print (var4) -- boolean
print (var5) -- string
type()
18
 字串必須寫在引號之間,可使用單引號或雙引號,但必須對稱使用
 可使用內建函式string.len()或在字串前加上#符號來取得字串⻑度
message = 'Print a string assigned to a variable'
print(message)
hello = 'hello, world'
-- Assign length to variables
count_hash = #hello;
count_func = string.len(hello)
print ('The string:')
print (hello)
-- Print the variables assigned at the top
print ('Has a length of:')
print (count_hash)
print(count_func)
-- Use string literals, in place
print (#'hello, world')
print (string.len('hello, world'))
string 1/3
19
 兩個字串可使用 .. 符號串接起來,注意在..前後⾄少都要保留⼀個
空白字元
name = 'Mike'
color = 'Blue'
-- Concatenate three strings
print ('Jill ' .. 'likes' .. ' Red')
-- Concatenate a variable and a strings
print ('Jack dislikes ' .. color)
-- Concatenate two variables and a string
print (name .. ' likes ' .. color)
-- Concatenate only variables
print (name .. color)
-- Assign result to variable
message = name .. ' likes ' .. color
print (message)
string 2/3
20
 其它資料與字串資料串接時,會自動轉為字串資料
 數值字串與其它數值資料運算時,會自動轉為數值資料
pi = 3.14
message = 'The value of pi is: ' .. pi
print(message)
print('Nine: ' .. 9)
eleven = '10' + 1
print (eleven) --11.0
print (7 + '01') -- 8.0
print (7 / '01') -- 7.0
string 3/3
21
 字串中要使用特殊字元時,必須使用轉義字元
 n: 換行
 t: 下⼀個⽔平定位點
 : 反斜線
 ': 單引號
 ": 雙引號
 [: 左中括弧
 ]: 右中括弧
message1 = 'he said 'bye' and left'
print (message1)
message2 = "he said 'bye' and left"
print (message2)
Escape characters
22
 io.read()函數用來自主控台讀取⼀行輸入,並以字串形式回傳
print ('Please enter your name:')
name = io.read()
print ('Hello ' .. name)
Console input
23
 範圍限制了在程序中可以存取變數的位置
 每個執行的Lua文件都是⼀個區塊。該區塊可以包含其他較小的區塊。
將其視為層次關係
Scope 1/5
24
 Lua使用do…end宣告區域區塊
-- main file chunk is anywhere in the file
do
-- local chunk
end
do
-- a different local chunk
end
 local關鍵字限制變數只在它所出現的區塊內有效
Scope 2/5
25
x = 3 -- x is accessable in the global chunk
print (x) -- will print: 3
print (y) -- will print: nil
print (z) -- will print: nil
local y = 4 -- y is accessable in the file chunk
-- The local keyword makes y local to the file
do
local z = 5 -- z is in a local chunk, in this example
-- that means local to the do/end block
print (x) -- will print: 3
print (y) -- will print: 4
print (z) -- will print: 5
end
print (x) -- will print: 3
print (y) -- will print: 4
print (z) -- will print: nil
Scope 3/5
26
 如果省略local關鍵字,則無論該變數是在哪個區塊中宣告,該變數
都是全域變數
x = 3 -- x is accessable in the global chunk
print (x) -- will print: 3
print (y) -- will print: nil
print (z) -- will print: nil
local y = 4 -- y is accessable in the file chunk
-- The local keyword makes y local to the file
do
z = 5 -- z is accessable in the global chunk
print (x) -- will print: 3
print (y) -- will print: 4
print (z) -- will print: 5
end
print (x) -- will print: 3
print (y) -- will print: 4
print (z) -- will print: 5
Scope 4/5
27
 區塊內宣告的區域變數名稱可以與全域變數相同名稱,在區塊內使用
的是區域變數,區塊外則使用全域變數,稱為variable shadowing
message = 'global-scope'
print ('message: ' .. message) -- Should print: global-scope
do
-- Shadow the message variable
local message = 'local-scope'
print ('message: ' .. message) -- Should print: local-scope
end
print ('message: ' .. message) -- Should print: global-scope
Scope 5/5
28
 函式本質上是被命名的程式區塊。與其它程式區塊不同的是,加載文
件時不會自動執行函式的內容
 首次加載文件時,僅定義函數。定義函數後,您可以根據需要調用函
式來執行該函數
 Scope規則適用於函式,作用與do/end區塊相同
Functions 1/7
29
 Defining a function
 以function關鍵字開頭。在function關鍵字之後,提供函數名稱
 函數名稱之後,必須提供參數列表。參數是用小括號()括起來的變數。
如果函數不需要參數,則參數列表可以為空,但仍需保留小括號()
 聲明參數列表後,開始編寫函數的主體。函數主體是⼀段程式碼,因此,
與其他區塊⼀樣,需要使用end關鍵字關閉主體
function PrintSomething()
text1 = 'hello'
text2 = 'world'
print (text1 .. ', ' .. text2)
end
Functions 2/7
30
 Calling a function
 定義函數後,就可以通過調用它來執行
 調用函數時,只需鍵入其名稱,然後加上括號。例如透過調用io.read(),
從控制台讀取輸入
function PrintSomething()
text1 = 'hello'
text2 = 'world'
print (text1 .. ', ' .. text2)
end
PrintSomething() -- call the function
PrintSomething() -- call the function
Functions 3/7
31
 Function arguments
 在定義函數時,可以在括號內放置⼀個或多個變數。這些變數是函數參數,
它們的作用區域就是函數區間
-- Declare the function, takes two arguments
function AddAndPrint(x, y)
local result = x + y;
print (x .. '+' .. y .. '=' .. result)
end
-- Call the function a few times
AddAndPrint(2, 3)
AddAndPrint(4, 5)
AddAndPrint(6, 7)
Functions 4/7
32
 Any number of arguments
 在Lua中,調用函式時不必提供與函式宣告相同數量的參數。多餘的參數
會被忽略,少給的參數值則為nil
-- Declare the function, takes two arguments
function AddAndPrint(x, y)
local result = x + y;
print (x .. '+' .. y .. '=' .. result)
end
-- Call the function a few times
AddAndPrint(2, 3) -- Will print 2+3=5
AddAndPrint(4, 5, 8, 9, 10) -- Will print 4+5=9
-- Declare the function, takes two arguments
function PrintValues(x, y)
print ('x: ' .. tostring(x) .. ', y: ' .. tostring(y))
end
-- Call the function a few times
PrintValues(3, 4) -- will print x: 3, y: 4
PrintValues(1) -- will print x: 1, y: nil
PrintValues() -- will print x: nil, y: nil
Functions 5/7
33
 Returning a value
 函式不僅接受輸入,還可以使用return將⼀些輸出返回給調用代碼。當函
式返回值時,可以將其作為運算式的⼀部分或獨立的指令敘述來調用
-- Declare the function
function SquareIt(number)
result = number * number
return result
end
-- Call the function
four = SquareIt(2)
print(four) -- Will print: 4
 注意:
Lua語言之return指令之後必須是end指令
Functions 6/7
34
 Returning multiple values
 Lua允許⼀個函式返回多個值。要返回多個值,只要將return回傳值間使
用逗號分隔
 與函式參數⼀樣,函式回傳值的個數不必與分配給它的變數數量匹配。如
果返回兩個值,但嘗試將它們分配給三個變數,額外變數的默認值為nil
-- Declare the function
function SquareAndCube(x)
squared = x * x
cubed = x * x * x
return squared, cubed
end
-- Call the function
s, c = SquareAndCube(2)
print ('Squared: ' .. s) -- will print: Squared: 4
print ('Cubed: ' .. c) -- will print: Cubed: 8
s, c, q = SquareAndCube(2) -- Call the same function
print ('Quartic: ' .. tostring(q)) -- will print: Quartic: nil
Functions 7/7
35
 Closures是⼀種透過匿名函式把區域變數與相關聯程式封裝閉合的機制,
能保存函式被建立時的執行環境(context),這「閉鎖」的環境中保存了
讓函數可以持續存取(甚⾄在function被return後)的獨立自由變數
function NextNumber()
local currentNumber = 0 -- local to the NextNumber function
return function () -- anonymous function
-- 因為這個匿名函式是建立在NextNumber函式內部,它可以看到NextNumber函式的全部成員
-- 並記錄其狀態,建立閉包
currentNumber = currentNumber + 1
return currentNumber
end
end
-- Assign the anonymous function to the variable next
next = NextNumber() -- create closure
print(next()) -- 1
print(next()) -- 2
print(next()) -- 3
-- currentNumber does not exist in a global context!
print(currentNumber) -- nil
Closures 1/2
36
 下列程式是使用Closures建立陣列的Iterator functions
days = { 'monday', 'tuesday', 'wednesday', 'thursday' }
function walk(array)
local index = 0
return function()
index = index + 1
return array[index]
end
end
for day in walk(days) do
print (day) -- 依序輸出4行星期名稱
end
Closures 2/2
37
 運算式是由運算元(operand)與運算子(operator)所組成的計算式
 運算子是指要進行的運算作業,例如+、-、*、/等
 運算元是運算作業的對象,運算元可以為變數、常值或是運算式
num = 5 + 3 - x
運算式
運算元 運算元 運算元運算元
運算子 運算子運算子
38
 Arithmetic operators
 addition operator (+)
 subtraction operator (-)
 multiplication operator (*)
 division operator (/)
 modulus operator (%)
x = 5 % 2 -- result is 1
y = 5.7 % 2 -- result is 1.7
z = 5.3 % 2.9 -- result is 2.4
 exponent operator (^)
運算子 1/5
39
 Relational operators
 equality operator (==)
 inequality operator (~=)
 greater than operator (>)
 greater than or equal to operator (>=)
 less than operator (<)
 less than or equal to operator (<=)
運算子 2/5
40
 Logical operators
 and operator (and)
如果第⼀個運算元為false,則回傳其第⼀個運算元;如果第⼀個運算元
為true,則回傳第二個運算元
x = true and false -- value is false
y = false and false -- value is false
z = true and true -- value is true
w = 7 and 1 -- value is 1
 or operator (or)
如果第⼀個運算元為true,則回傳其第⼀個運算元;如果第⼀個運算元為
false,則回傳第二個運算元
x = true or false -- value is true
y = false or false -- value is false
z = true or true -- value is true
w = 7 or 1 -- value is 7
 and/or運算都使用快捷評估。換言之,必要時才會評估第二個運算元
運算子 3/5
41
 not operator (not)
x = not true -- false
y = not true or false -- false
z = not not false -- false
w = not (7 + 1) -- false
運算子 4/5
42
 Operator precedence
運算子 5/5
43
^
not # -(unary)
* / %
+ -
..
< > <= >= ~= ==
and
or
高優先序
低優先序
 if敘述
if condition then
code block
end
print('Enter your name')
name = io.read()
if #name <= 3 then
print("that's a short name, " .. name)
end
流程控制 1/4
44
 if … else敘述
if condition then
code block 1
else
code block 2
end
print('Enter a number')
x = io.read()
if x % 2 == 0 then
print(x .. ' is even')
else
print(x .. ' is odd')
end
流程控制 2/4
45
 if … elseif敘述
if condition 1 then
code block 1
elseif condition 2 then
code block 2
...
elseif condition n then
code block n
else
code block
end
流程控制 3/4
46
print('Enter your name')
name = io.read()
if #name <= 3 then
print('that's a short name, ' .. name)
elseif #name <= 6 then
print(name .. ' is an average length name')
else
print(name .. ' is a long name')
end
流程控制 4/4
47
 while迴圈
while condition do
-- chunk
end
x = 10 -- Initialize a 'control' variable
while x > 0 do -- Boolean condition: x > 0
print('hello, world')
x = x - 1 -- Decrement the 'control' variable
end
迴圈 1/4
48
 break指令可強制中止迴圈 (須搭配if指令)
x = 0
while x < 10 do -- Execute 10 times!
print('x is ' .. x)
if x == 5 then
break -- This stops the loop execution at 5
end
x = x + 1
end
迴圈 2/4
49
 repeat迴圈
repeat
-- chunk
until condition
x = 10 -- Initialize a 'control' variable
repeat
print('hello, world')
x = x - 1 -- Decrement the 'control' variable
end x == 0 -- Boolean condition: x == 0
迴圈 3/4
50
 for迴圈
for variable = initial_exp, final_exp, step_exp do
-- chunk
end
for i = 0, 10, 1 do
print(i)
end
迴圈 4/4
51
 table是Lua唯⼀的資料結構
 建立table
 table內容須置於大括弧內
tbl = {} -- Creates table, assigns it to tbl variable
print('The type of a table is: ' .. type(tbl))
 table內容為鍵-值對 (key-value pair),每組資料以逗號分隔
key1 = value1, key2 = value2, ...
 若鍵為數值或單⼀字元,則必須置於中括弧內
vector1 = {[1]='x', [2]='y', [3]='z', [4]=23}
 當鍵值是數值資料,table作用為陣列資料;
vector = {'x', 'y', 'z', 23} -- 使用預設key,數值1, 2, 3, 4
 當鍵值混雜非數值資料,table作用為字典資料
colors = {red = '#ff0000', green = '#00ff00', blue = '#0000ff'}
tables 1/5
52
 建立table時可⼀併給定初始值,若鍵為數值或單⼀字元,則必須置
於中括弧內
colors = {
red = '#ff0000',
green = '#00ff00',
blue = '#0000ff'
}
colors2 = {red = '#ff0000', ['g'] = '#00ff00', [3] = '#0000ff'}
print('red: ' .. colors.red)
print('red: ' .. colors['red'])
print('green: ' .. colors2.g)
print('blue: ' .. colors2[3])
tables 2/5
53
 存取資料
 table的鍵可使用除了nil之外的任何資料
 鍵須置於中括弧內
 如果鍵為字串型別,可使用.運算子
 如果table中不存在該鍵,則其值為nil
tbl = {}
tbl['x'] = 20
tbl[3] = 'x'
i = 'x'
print(tbl['x']) -- 20
print(tbl[i]) -- 20
print(tbl.x) -- 20
tbl.y = 10
print('x + y: ' .. tbl.x + tbl.y) -- x + y: 30
print(tbl['z']) -- nil
tables 3/5
54
 對⼀般變數⽽言,將變數指定給另⼀個變數,每個變數各別擁有自⼰
的副本
x = 10 -- y assigned 10 by value
y = x -- y assigned the value of x (10) by value
x = 15 -- x assigned 15 by value
print(x) -- 15
print(y) -- 10
tables 4/5
55
 將table變數指定給另⼀個變數,兩個變數是引用同⼀份table資料
a = {} -- a is assigned a table reference
b = a -- b references the same table as x
print(a)
print(b)
b.x = 10 -- also creates a.x, a and b reference the same table
a.y = 20 -- also creates b.y, a and b reference the same table
a.x = 30 -- also changes b.x, a and b reference the same table
print('a.x: ' .. a.x) -- print a.x: 30
print('b.x: ' .. b.x) -- print b.x: 30
print('a.y: ' .. a.y) -- print a.y: 20
print('b.y: ' .. b.y) -- print b.y: 20
a = nil -- a no longer references the table
b = nil -- nothing references the table after this
 當變數a和b都設置為nil,table內容已沒有被任何變數引用,系統就可對
它進行垃圾回收
tables 5/5
56
 當table符合以下條件,lua才會以連續空間儲存資料,形成陣列
 使用整數資料當鍵(索引)
 鍵(索引)值從1開始
arr = {}
arr[1] = 'x'
arr[2] = 'y'
arr[3] = 'z'
for i = 1, 3 do
print(arr[i])
end
 lua陣列元素允許是不同資料型別
Arrays 1/4
57
 建立table時,若全部未指定鍵值,會自動形成陣列
vector = { 'x', 'y', 'z', 23}
print(tostring(vector[0])) -- nil, the array starts at 1
print(vector[1]) -- first element, x
print(vector[2]) -- second element, y
print(vector[3]) -- third element, z
print(vector[4]) -- fourth element, 23
Arrays 2/4
58
 大部分程式語言,陣列索引值從0開始,你可以透過下列方式來達成,
但這樣做違反Lua慣用法,使用#運算子時可能造成難以捉摸的細微錯
誤
vector = { [0] = 'x', 'y', 'z', 'w', 23 }
print(vector[0]) -- element before first, x
print(vector[1]) -- first element, y
print(vector[2]) -- second element, z
print(vector[3]) -- third element, w
print(vector[4]) -- third element, 23
Arrays 3/4
59
 lua陣列可以是稀疏的(Sparse arrays),即陣列中可以元素無資料,
這些位置的值為nil
arr = { }
arr[1] = 'x'
arr[2] = 'y'
-- arr[3] is nil by default
-- arr[4] is nil by default
arr[5] = 'z'
arr[6] = 'w'
for i = 1, 6 do
print(tostring(arr[i]))
end
Arrays 4/4
60
 #運算子也可以用來取得陣列⻑度,但使用時要特別小心
 #運算子只會從索引值1開始計算陣列⻑度
arr = { }
arr[0] = 'x' -- not counted towards length
arr[1] = 'y'
arr[2] = 'z'
length = #arr -- length = 2
print('array length: ' .. length)
 #運算子找到連續二個nil即視為陣列結束,因此使用#運算子計算稀疏陣
列⻑度可能錯誤
 ⼀般會採用Iterating方式來遍覽陣列元素
陣列長度
61
 lua不支援多維陣列,但可以透過建立an array of arrays (實際
上是a table of tables)來達成
num_rows = 4
num_cols = 4
values = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P'}
value = 1
matrix = {} -- create new matrix
for i = 1, num_rows do
matrix[i] = {} -- create new row (matrix)
for j = 1, num_cols do
-- current element: row i, column j
matrix[i][j] = values[value] -- assign element to column
value = value + 1 -- move to next letter
end
end
print(matrix[1][1]) -- A
print(matrix[2][4]) -- H
print(matrix[3][4]) -- L
多維陣列
62
 在Lua中,可以使用泛型for迴圈來遍覽table或array的所有元素
 table資料使用pairs遍覽函式
vector = { x = 34, y = 22, z = 56 }
for k, v in pairs(vector) do
print('key: ' .. k .. ', value: ' .. v)
end
Iterating 1/2
63
 array資料使用ipairs遍覽函式
days = { 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday',
'sunday' }
for i, v in ipairs(days) do
print('index: ' .. i .. ', value: ' .. v)
end
Iterating 2/2
64
 Lua中,可透過mata tables來修改table的行為。任何table都可以
修改成為meta table,任何table可以有⼀個meta table,⽽meta
table也可有自⼰的meta table
 meta table使用meta methods來變更table的行為
 meta methods是具有特定名稱的函數,這些函數會影響table的行為
Mata tables 1/3
65
 創建資料表時,並不會自動設定其meta table,預設的meta table
值為nil
 setmetatable方法為資料表設定meta table
 setmetatable(table_name, meta-table_name)
 Lua允許使用任何資料表做為meta table,甚⾄可以使用自身做為
meta table
Mata tables 2/3
66
 getmetatable方法用來讀取meta table設定值
x = {}
y = {}
z = {}
setmetatable(y, z)
setmetatable(z, z)
print(getmetatable(x)) -- nil
print(getmetatable(y)) -- random-looking number is the unique ID for table z
print(getmetatable(z)) -- random-looking number is the unique ID for table z
Mata tables 3/3
67
 在meta table中具有特定名稱的元方法
 __index
 讀取資料表中不存在的資料欄時,則會觸發執行__index元方法。如果不
存在__index元方法,則返回nil;如果存在,則返回結果
x = {}
z = {foo = 'bar'}
setmetatable(x, z)
print(x.foo) -- nil
print(z.foo) -- bar
Mata methods 1/10
68
x = {}
z = {
foo = 'bar',
__index = function(table, key)
return z[key]
end
}
setmetatable(x, z)
print(x.foo) -- bar, lives in z
print(z.foo) -- bar
Mata methods 2/10
69
 __newindex
 當對表中不存在的資料欄進行賦值時,就會自動調用__newindex元方法建
立鍵-值對
x = { }
z = {
__index = function(table, key)
return z[key]
end,
__newindex = function(table, key, value)
z[key] = value
end
}
setmetatable(x, z)
x.foo = 'bar' -- 由於x沒有foo成員,會調用其meta table中的__newindex方法
print(x.foo) -- bar, lives in z
print(z.foo) -- bar
Mata methods 3/10
70
 rawget(table, key)
 讀取table中的key鍵對應的資料值,但如果鍵值不存在時不會觸發執行
__index元方法
 rawset(table, key, value)
 設定table中的key:value資料對,但如果鍵值不存在時不會觸發執行
__newindex元方法
Mata methods 4/10
71
x = { }
y = { }
z = {
__index = function(table, key)
return z[key]
end,
__newindex = function(table, key, value)
z[key] = value
end
}
setmetatable(x, z)
setmetatable(y, z)
x.foo = 'bar' -- Sets 'bar' in z
print(x.foo) -- bar, lives in z
rawset(x, 'foo', 'raw') -- Sets 'raw' in x directly!
print(x.foo) -- raw, lives in x
print(y.foo) -- bar, lives in z
print(rawget(y, 'foo')) -- nil
Mata methods 5/10
72
 __call
 __call可將資料表用作函數,稱為functable
 __call具有可變數量的參數,第⼀個參數為資料表本身;隨後是呼叫
functable時實際的任意數量的參數
tbl = {
__call = function(table, val1, val2)
return 'Hello, from functor: ' .. (val1 + val2)
end
}
setmetatable(tbl, tbl)
message = tbl(2, 3); -- Calling the table like a function!
print('message: ' .. message) -- message: Hello, from functor: 5
Mata methods 5/10
73
 可實作以下meta method來實現Table運算
 __add:對應+運算子
 __sub:對應-運算子
 __mul:對應*運算子
 __div:對應/運算子
 __mod:對應%運算子
 __pow:對應^運算子
 __eq:對應==運算子
 __lt:對應<運算子
 __le:對應<=運算子
Mata methods 6/10
74
 __len:對應#運算子,預期回傳table的鍵-值對數量
employee1 = {name = 'tony', age = 25}
print (#employee1) -- 0
meta_tbl = {
__len = function(mytable)
len = 0
for k, v in pairs(mytable) do
len = len + 1
end
return len
end
}
setmetatable(employee1, meta_tbl)
print (#employee1) -- 2
Mata methods 7/10
75
 __tostring:預期回傳table的內容(字串形式)
employee1 = {name = 'tony', age = 25}
print (employee1) -- table: 00000000006f9bd0
meta_tbl = {
__tostring = function(mytable)
str = '{'
for k, v in pairs(mytable) do
str = str .. k .. ':' .. v .. ', '
end
str = str .. '}'
return str
end
}
setmetatable(employee1, meta_tbl)
print (employee1) -- {age:25, name:tony, }
Mata methods 8/10
76
 __concat:對應..運算子,預期將串接兩個table內容
function table_maxn(t)
local mn = 0
for k, v in pairs(t) do
if mn < k then
mn = k
end
end
return mn
end
-- 两表相加操作
mytable = setmetatable({ 1, 2, 3 }, {
__concat = function(mytable, newtable)
for i = 1, table_maxn(newtable) do
table.insert(mytable, table_maxn(mytable)+1,newtable[i])
end
return mytable
end
})
Mata methods 9/10
77
secondtable = {4, 5, 6}
mytable = mytable .. secondtable
for k,v in ipairs(mytable) do
print(k,v)
end
Mata methods 10/10
78
 math.acos(v)
回傳反餘弦值,v為弳度值
 math.asin(v)
回傳反正弦值,v為弳度值
 math.atan(v)
回傳反正切值,v為弳度值
 math.atan(x, y)
回傳x/y的反正切值,x/y為弳度值
 math.cos(v)
回傳餘弦值,v為弳度值
Lua內建數學函式 1/7
79
 math.sin(v)
回傳正弦值,v為弳度值
 math.tan(v)
回傳正切值,v為弳度值
 math.deg(v)
將弳度值v轉換為角度值
 math.rad(v)
將角度值v轉換為弳度值
 math.abs(v)
回傳v的絕對值
 math.tointeger(v)
如果v可轉換為整數值,回傳整數值,否則回傳nil
Lua內建數學函式 2/7
80
 math.max(x, y)
回傳x與y中的較小值
 math.min(x, y)
回傳x與y中的較大值
 math.ult(x, y)
如果x值小於y,回傳true
Lua內建數學函式 3/7
81
 math.random()
回傳⼀個介於0與1間的實數值
 math.random(max)
回傳⼀個介於1與max間的整數值
 math.random(min, max)
回傳⼀個介於min與max間的整數值
 math.randomseed(v)
設定v為亂數種子
 os.time()
回傳自1970.1.1.08:00迄今的秒數
Lua內建數學函式 4/7
82
math.randomseed(os.time())
print ('Guess a number between 10 and 100')
number = math.random(10, 100)
-- print ('Random: ' .. number)
repeat
local guess = tonumber( io.read() )
if guess ~= nil then
if guess == number then
print ('You guessed the number.')
break
elseif guess < number then
print ('Too low, guess again.')
else
print ('Too high, guess again.')
end
end
until false
Lua內建數學函式 5/7
83
 math.ceil(v)
大於v的最小整數
 math.floor(v)
小於v的最大整數
 math.fmod(x, y)
回傳x/y運算的餘數
 math.modf(v)
回傳兩個值,v的整數部分和小數部份
print(math.ceil(10.3)) -- 11
print(math.floor(10.3)) -- 10
print(math.fmod(10, 0.3)) -- 0.1
x, y = math.modf(10.3)
print(x, y) -- 10 0.3
Lua內建數學函式 6/7
84
 math.sqrt(v)
回傳v的平方根值
 math.type(variable)
回傳變數型別名稱(字串),integer、float或nil
Lua內建數學函式 7/7
85
 math.pi
表示圓周率值
 math.huge
表示正無限大
 math.mininteger
表示最小整數
 math.maxinteger
表示最大整數
Lua內建常數
86
 io.open(filename, mode)
開啟檔案。開檔成功回傳file handle,否則回傳nil
 filename檔案名稱字串
 Mode檔案模式字串
 'r':唯讀模式,為預設值
 'w':寫入模式。若檔案不存在,會建立新檔;若檔案存在,則覆寫內容,
 'a':附加模式,若檔案不存在,會建立新檔;若檔案存在,則寫入的資
料會附加在檔尾
 'r+':讀寫模式,若檔案不存在,回傳nil。若檔案存在,可讀取檔案
內容,或覆寫檔案內容
 'w+':同'w'模式,但也允許讀取檔案內容
 'a+':同'a'模式,但也允許讀取檔案內容
檔案作業 1/6
87
 filehandle:write('text')
寫入資料到檔案
file = io.open('data.txt', 'w')
file:write('foo', 'n')
file:write('barn')
-- Create function to save character data
function SaveCharacterData(name, power, team)
file:write('name ' .. name .. 'n') -- We can concatenate with ..
file:write('attack ', power, 'n') -- or use a comma seperated list
file:write('team ' .. team, 'n') -- we can even mix & match!
end
-- Call the function
SaveCharacterData('gwen', 20, 'blue')
檔案作業 2/6
88
 filehandle:lines()
讀取檔案全部內容(以行為單位)
file = io.open('data.txt')
lines = file:lines()
print('Contents of file:');
for line in lines do
print('t' .. line)
end
檔案作業 3/6
89
 filehandle:read(v)
依據參數v之設定,讀取檔案內容
 n
讀取n個字元資料
 '*n'
讀取⼀個數值資料
 '*a'
讀取到檔案結尾的全部資料,如果已在檔案結尾,回傳空字串
 '*l'
預設參數值。讀取下⼀行資料(跳過換行字元),如果已在檔案結尾,回傳
nil
檔案作業 4/6
90
hero = {}
f = io.open('data.txt')
f:read() -- Reads to end of line
f:read() -- Reads to end of line
f:read(5) -- read in 'name ' and discard it
hero.name = f:read() -- Reads to end of line, store name
f:read(7) -- read in 'attack ' and discard it
hero.health = f:read('*n') -- read the next number
f:read(6) -- read in 'team ' and discard it
hero.team = f:read('*l')-- Same as reading in the name
print ('hero')
print ('tname: ' .. hero.name )
print ('thealth: ' .. hero.health)
print ('tteam: ' .. hero.team)
檔案作業 5/6
91
 filehandle:close()
關閉檔案
local file = io.open('data.txt', 'w')
file:write('foo', 'n')
file:write('bar')
file:close() -- THIS IS NEW! Don't forget to close!
 os.rename('new_file.txt', 'renamed_file.txt')
變更檔名
 os.remove('renamed_file.txt')
刪除檔案
 os.execute('mkdir new_folder')
建立目錄
檔案作業 6/6
92
 os.clock()
回傳lua程式執行迄今的秒數
 os.date('format')
作業系統API
93
 string.find(str1, str2)
在str1中尋找str2子字串,回傳子字串起始位置索引,找不到時回傳
nil
 string.sub(str, start, end)
回傳從start到end之子字串,省略end參數則預設到字串結尾
local sentence = 'The quick brown fox'
local word = 'quick'
local start = string.find(sentence, word)
print ('substring found at index: ' .. start) -- 5
start = start + #word + 1
local result = string.sub(sentence, start)
print (result) -- brown fox
字串處理作業 1/2
94
 string.upper(str)
將字串轉換為大寫字⺟
 string.lower(str)
將字串轉換為大寫字⺟
 string函式庫支援使用:運算元,先前程式可改寫如下:
local sentence = 'The quick brown fox'
local word = 'quick'
local start = sentence:find(word)
print ('substring found at index: ' .. start) -- 5
start = start + #word + 1
local result = sentence:sub(start)
print (result) -- brown fox
字串處理作業 2/2
95
 使用模組可將程式碼拆解成不同程式檔,方便管理維護
 Lua模組就是⼀個Lua檔案,內容是⼀般的Lua table宣告,會回傳⼀
個Lua table
 程式中使用require函式載入Lua模組。require函式參數為要載入的
文件的名稱(不用加.lua副檔名)
使用模組 1/6
96
-- module_character.lua
local character = {} -- It's important that the table retuned be local!
character.health = 20
character.strength = 5
character.name = ''
character.new = function (self, object)
object = object or {} -- Use provided table, or create new one
local provided = ''
if type(object) == 'string' then
provided = object
object = {}
end
setmetatable(object, self) -- Assign meta table
self.__index = self
if provided ~= '' then
object.name = provided
end
return object
end
使用模組 2/6
97
character.attack = function(self, other)
print (self.name .. ' attacks ' .. other.name)
other.health = other.health - self.strength
if other.health < 1 then
print ('t' .. other.name .. ' is dead')
else
print ('t' .. other.name .. ' has ' .. other.health .. ' health left')
end
end
return character
使用模組 3/6
98
-- module_main.lua
-- load the character module into a table named character
Character = require ('module_character')
-- Create a new hero, which is a charcter
gwen = Character:new('gwen')
gwen.strength = 10
-- Create a new enemy, also a character
orc = Character:new('orc')
-- Run game logic
gwen:attack(orc)
orc:attack(gwen)
gwen:attack(orc)
使用模組 4/6
99
 能夠簡單地加載Lua table是⼀種強大的機制,如果將保存數據格式
化為有效的Lua文件,則可以將其作為模塊加載回去。使用Lua的此功
能,就不需要自行撰寫程式解析文本文件
 require函數不會重複載入文件。因此,若想重複載入資料文件,要
使用dofile函數
-- module_save.lua
function Save(level, health, lives)
file = io.open('save_data.lua', 'w')
file:write('return { n')
file:write('tlevel = ', level, ',', 'n')
file:write('thealth = ', health, ',', 'n')
file:write('tlives = ', lives, 'n')
file:write('}')
file:close()
end
使用模組 5/6
100
-- module_main2.lua
require('module_save')
Save(20, 10, 2)
gameData = dofile('save_data.lua') -- 檔案含附檔名
print('Loaded:')
print('tlevel: ' .. gameData.level)
print('thealth: ' .. gameData.health)
print('tlives: ' .. gameData.lives)
Save(10, 10, 5)
gameData = dofile('save_data.lua')
print('Loaded:')
print('tlevel: ' .. gameData.level)
print('thealth: ' .. gameData.health)
print('tlives: ' .. gameData.lives)
使用模組 6/6
101
 Lua並未支援原生的物件導向程式設計類別(class)機制,但運用
meta table也可以實現類似功能
Enemy = { }
Enemy.health = 200
Enemy.attack = 4
Enemy.defense = 20
Enemy.new = function (self, object)
object = object or {} -- Use provided table, or create new one
setmetatable(object, self) -- Assign meta table
self.__index = self
return object
end
Enemy.hit = function(self, damage)
damage = damage - self.defense
if damage < 0 then
damage = 0
end
self.health = self.health - damage
end
物件導向程式設計 1/13
102
grunt = Enemy.new(Enemy) -- Health is stored in 'Enemy'
miniBoss = Enemy.new(Enemy) -- Health is stored in 'Enemy'
boss = Enemy.new(Enemy, {health = 500, defense = 100})
miniBoss.health = 250 -- Health is now stored in 'miniBoss'
-- grunt does not have a health variable, so the enemy table health is returned
print ('grunt health: ' .. grunt.health) -- 200
-- miniBoss has a health variable, it was created in the above assignment
print ('mini boss health: ' .. miniBoss.health) --250
-- boss also has a health variable, so the boss table health is returned
print ('boss health: ' .. boss.health) -- 500
print ('Hero attacks both boss and grunt')
Enemy.hit(boss, 50)
Enemy.hit(grunt, 55)
print ('grunt health: ' .. grunt.health) -- 165
print ('boss health: ' .. boss.health) -- 500
物件導向程式設計 2/13
103
物件導向程式設計 3/13
104
 冒號(:)運算子
 在定義類別方法時,第⼀個參數必須是self。⽽在調用物件方法時,必須
將物件實體傳給第⼀個參數
 使用冒號(:)運算子可簡化調用物件方法程式碼
grunt = Enemy.new(Enemy)
boss = Enemy.new(Enemy, {health = 500, defense = 100})
Enemy.hit(boss, 50)
Enemy.hit(grunt, 55)
 可簡化為
grunt = Enemy:new() -- self = Enemy
boss = Enemy:new({health = 500, defense = 100})
boss:hit(50)
grunt:hit(55)
物件導向程式設計 4/13
105
 處理物件內的table資料
 當table變數指定給另⼀個變數,兩個變數是引用同⼀份資料;因此,如
果物件內含有table資料時,即使建構不同物件,物件內的table資料是共
用的
Character = {
alive = true
}
Character.position = {
x = 10, y = 20, z = 30
}
Character.new = function(self, object)
object = object or {}
setmetatable(object, self)
self.__index = self
return object
end
物件導向程式設計 5/13
106
player1 = Character:new()
player2 = Character:new()
player1.position.x = 0
player2.position.y = 10
print ('Player 1, position: (' .. player1.position.x .. ', '
.. player1.position.y .. ', ' .. player1.position.z .. ')')
print ('Player 2, position: (' .. player2.position.x .. ', '
.. player2.position.y .. ', ' .. player2.position.z .. ')')
print ('Table id:')
print ('Player 1: ' .. tostring(player1.position))
print ('Player 2 :' .. tostring(player2.position))
if player1.position == player2.position then
print ('Player 1 and 2 have the same position reference');
else
print ('Player 1 and 2 have unique positon tables');
end
物件導向程式設計 6/13
107
物件導向程式設計 7/13
108
 解決方式是在設置物件的meta table之前為每個實例配置各自的table
Character = {
alive = true
}
Character.position = {
x = 10, y = 20, z = 30
}
Character.new = function(self, object)
object = object or {}
-- Assign per instance variables after the object is valid but before
-- setting the meta table! Copy all members of the new table by value!
object.position = {}
object.position.x = Character.position.x
object.position.y = Character.position.y
object.position.z = Character.position.z
setmetatable(object, self)
self.__index = self
return object
end
物件導向程式設計 8/13
109
player1 = Character:new()
player2 = Character:new()
player1.position.x = 0
player2.position.y = 10
print ('Player 1, position: (' .. player1.position.x .. ', '
.. player1.position.y .. ', ' .. player1.position.z .. ')')
print ('Player 2, position: (' .. player2.position.x .. ', '
.. player2.position.y .. ', ' .. player2.position.z .. ')')
print ('Table id:')
print ('Player 1: ' .. tostring(player1.position))
print ('Player 2 :' .. tostring(player2.position))
if player1.position == player2.positon then
print ('Player 1 and 2 have the same position reference');
else
print ('Player 1 and 2 have unique positon tables');
end
物件導向程式設計 9/13
110
物件導向程式設計 10/13
111
 繼承性 (inheritance)
Animal = {
sound = ''
}
Animal.new = function(self, object)
object = object or {}
setmetatable(object, self)
self.__index = self
return object
end
Animal.MakeSound = function(self)
print(self.sound)
end
-- Dog is a class, not an object (instance)
Dog = Animal:new()
Dog.sound = 'woof'
物件導向程式設計 11/13
112
-- Cat is a class, not an Object (instance)
Cat = Animal:new()
Cat.sound = 'meow'
Cat.angry = false
Cat.MakeSound = function(self)
if self.angry then
print('hissss')
else
print(self.sound)
end
end
animals = { Cat:new(), Dog:new(), Cat:new() }
animals[1].angry = true
for i,v in ipairs(animals) do
-- The current animal is stored in the v variable. It doesn't matter if
-- the animal is a Dog or a Cat Both Dog and Cat extend Animal, which is
-- guaranteed to contain a MakeSound function.
v:MakeSound()
end
物件導向程式設計 12/13
113
物件導向程式設計 13/13
114

More Related Content

PDF
[ZigBee 嵌入式系統] ZigBee Architecture 與 TI Z-Stack Firmware
PDF
Fun with Network Interfaces
PDF
Freeswitch
PDF
コルーチンの使い方
PDF
DMVPN Lab WorkBook
PDF
Basic linux commands
PDF
Fun with PRB, VRFs and NetNS on Linux - What is it, how does it work, what ca...
[ZigBee 嵌入式系統] ZigBee Architecture 與 TI Z-Stack Firmware
Fun with Network Interfaces
Freeswitch
コルーチンの使い方
DMVPN Lab WorkBook
Basic linux commands
Fun with PRB, VRFs and NetNS on Linux - What is it, how does it work, what ca...

What's hot (8)

PDF
Karatê DSL - Automatizando testes de API de forma simples - GUTS RS - Junho
PDF
BPF / XDP 8월 세미나 KossLab
PDF
Minicurso Shell Script
PDF
Linux Kernel Cryptographic API and Use Cases
PPT
PDF
kyotolisp#1 LT3 美しいLispの書き方 (1)
PPTX
Fixed Length Subnetting about ip address.pptx
PPTX
Bash Shell Scripting
Karatê DSL - Automatizando testes de API de forma simples - GUTS RS - Junho
BPF / XDP 8월 세미나 KossLab
Minicurso Shell Script
Linux Kernel Cryptographic API and Use Cases
kyotolisp#1 LT3 美しいLispの書き方 (1)
Fixed Length Subnetting about ip address.pptx
Bash Shell Scripting
Ad

Similar to nodeMCU IOT教學02 - Lua語言 (20)

PPTX
Corona 初探 lua 語言,玩跨平台(iOS & android) 行動裝置開發工具
PPTX
流程語法與函式
PDF
Ch9 教學
PPT
Python Basic
PDF
PDF
程式人雜誌 -- 2014 年2月號
PDF
4. 流程語法與函式
PDF
Python基本資料運算
ODP
Ruby程式語言入門導覽
PDF
lambda/closure – JavaScript、Python、Scala 到 Java SE 7
PPTX
Y3CDS - Python class 01
PDF
Python 2 - 快速簡介
PDF
Programming python - part 1
PDF
PDF
Ch10 教學
PPT
1 C入門教學
PDF
Ruby 使用手冊 (Part 1)
ODP
Op 20090411
DOCX
系統程式 -- 第 7 章 高階語言
PDF
實踐大學教案20140329
Corona 初探 lua 語言,玩跨平台(iOS & android) 行動裝置開發工具
流程語法與函式
Ch9 教學
Python Basic
程式人雜誌 -- 2014 年2月號
4. 流程語法與函式
Python基本資料運算
Ruby程式語言入門導覽
lambda/closure – JavaScript、Python、Scala 到 Java SE 7
Y3CDS - Python class 01
Python 2 - 快速簡介
Programming python - part 1
Ch10 教學
1 C入門教學
Ruby 使用手冊 (Part 1)
Op 20090411
系統程式 -- 第 7 章 高階語言
實踐大學教案20140329
Ad

More from 吳錫修 (ShyiShiou Wu) (20)

PDF
Vuforia AR影片程式設計
PDF
micro:bit亮度感測應用
PDF
Vuforia AR 同時追踨多張辨識圖
PDF
micro:bit開關控制應用
PDF
Vuforia AR 應用程式設計入門
PDF
Vuforia AR 應用程式準備作業
PDF
micro:bit LED顯示控制
PDF
IDE for micro:bit
PDF
Microbit 1 introduction
PDF
Arduino overview
PDF
使用Makeblock App學習mBot程式設計
PDF
使用M部落App學習mBot程式設計
PDF
nodeMCU IOT教學03 - NodeMCU導論
PDF
Unity遊戲程式設計 - 2D Platformer遊戲
PDF
Unity遊戲程式設計 - 2D移動與碰撞處理II
PDF
Unity遊戲程式設計 - 2D運動與碰撞處理I
PDF
Python與Ardinio整合應用
PDF
mBlock積木式設計程式
PDF
Arduino程式除錯
PDF
Unity遊戲設計- 2D動畫製作及應用
Vuforia AR影片程式設計
micro:bit亮度感測應用
Vuforia AR 同時追踨多張辨識圖
micro:bit開關控制應用
Vuforia AR 應用程式設計入門
Vuforia AR 應用程式準備作業
micro:bit LED顯示控制
IDE for micro:bit
Microbit 1 introduction
Arduino overview
使用Makeblock App學習mBot程式設計
使用M部落App學習mBot程式設計
nodeMCU IOT教學03 - NodeMCU導論
Unity遊戲程式設計 - 2D Platformer遊戲
Unity遊戲程式設計 - 2D移動與碰撞處理II
Unity遊戲程式設計 - 2D運動與碰撞處理I
Python與Ardinio整合應用
mBlock積木式設計程式
Arduino程式除錯
Unity遊戲設計- 2D動畫製作及應用

nodeMCU IOT教學02 - Lua語言