這是一篇文章能讓你10 分鐘學會lua 基本用法的教學文
底下是這篇文章會介紹到的基本用法,灰色部分會在其他章節中另外介紹
Lua Basics
Comment
String
Number
Variable scope
Ternary Operator
Loop Activity(while, repeat)
Table
Multiple Assignment
Function
Module
Metatables
Prototype Based OO Programming
LuaJIT - FFI Library
#Lua Basic
Comment
-- comment | |
--[[ | |
multiline | |
]] |
String
-- 字串可以直接assign 給變數 | |
local name = "Iris" | |
-- 字串前面加上#可以取得字串長度 | |
print('Size of string is ' .. #name) | |
-- 多行字串可以用兩個中括號包起來 | |
local substring = [[I am a long long long long | |
long | |
......string ~ | |
]] | |
print(substring) | |
-- 在lua中 字串的連接是用'..'做到的 | |
local str = name ..'+'.. substring | |
print(str) | |
輸出結果如下
Size of string is 4
Number
--在lua中,沒有區分小數(float)或是整數(int),只有number一種變數類型 | |
-- lua 5.3目前支援的最大整數是2^63 -1 | |
bigNum = 9223372036854775807 | |
-- 可以用type()印出參數類型 | |
print('Type is ' .. type(bigNum)) | |
print(bigNum) | |
-- 這邊可以看到 如果+1之後 bigNum會overflow | |
bigNum = bigNum + 1 | |
print(bigNum) | |
-- 小數精準度則是到小數點後13位 | |
floatprecision = 1.12345678901234567890 | |
print('float precision is ' .. floatprecision) | |
輸出結果如下
Type is number
9223372036854775807
-9223372036854775808
float precision is 1.1234567890123
Variable scope
age = 13 | |
-- 因為 age < 16所以會跑進if這個scope 中 | |
if age < 16 then | |
print('You can go to school') | |
-- 新增一個區域變數,這個區域變數只能在if這個scope中生效,其他scope無法使用 | |
local Ver = 10 | |
print(Ver) -- local | |
elseif (age >= 16) and (age < 20) then | |
print('You can drive') | |
print(Ver) -- nil | |
else | |
print('You can vote') | |
print(Ver) -- nil | |
end | |
print(Ver) -- nil | |
輸出結果如下
You can go to school
10
nil
Ternary Operator (三元運算子)
如果寫過C的寶寶們應該知道 x = (condition) ? (if-match) :( if not match) 這種寫法,在lua也有喔 只是? :變成and 和 or
local x = -1 | |
-- like c++ | |
-- string sign = (x < 0) ? “ negative” : “non-negative” | |
local sign = x < 0 and 'negative' or 'non-negative' | |
print('x is ' .. sign) | |
-- 也可以嵌入進print裡面 | |
print('x is ' .. (x < 0 and 'negative' or 'non-negative')) | |
輸出結果如下
x is negative
x is negative
Loop Activity
在lua中的迴圈可以簡單分為三種 for, while..do, repeat...until,因為for在很多範例中會介紹,這裡就不多介紹
- while
i = 0 | |
-- while loop用法是 while (condition) do ... end | |
while true do | |
i = i + 1 | |
print('i= ' .. i) | |
-- %是取餘數,如果是雙數的話,就直接從新進入迴圈(continue) | |
if i % 2 == 0 then | |
print('continue') | |
-- 因為lua沒有continue的功能,所以通常大家都會用goto來模擬 | |
goto continue | |
elseif i == 3 then | |
print('break') | |
-- 可以用break直接離開迴圈 | |
break | |
end | |
print('end') | |
::continue:: | |
end |
輸出結果如下
i= 1
end
i= 2
continue
i= 3
break
- repeat
value = 3 | |
repeat | |
print('value is: ' .. value) | |
value = value - 1 | |
-- 直到符合until中的條件才會離開迴圈 | |
until (value < 0) |
輸出結果如下
value is: 3
value is: 2
value is: 1
value is: 0
Table
Table,我覺得這可以說是lua實現黑魔法的開始,table中可以放各種東西,function, string, number...所有東西都能放到table並且也可以輕鬆地使用
先從一個簡單的例子來看
-- 我們在table裡面放入字串 | |
local months = {"January", "February", "March", "April"} | |
-- 如果沒有assign key值的話,就是從1開始 (lua是1 base的) | |
for key, value in pairs(months) do | |
print('(' .. key .. ')' .. value) | |
end | |
-- 可以用table[key]取的對應的value | |
print('* ' .. months[1]) | |
-- 如果再table中的項目都是同類型的,前面加上#就能取得他的項目數量 | |
print('Number of Items is ' .. #months) |
輸出結果如下
(1)January
(2)February
(3)March
(4)April
* January
Number of Items is 4
那如果我們在table中塞入不同類型的參數就如下面
-- 寫個簡單的函數 | |
local function func() | |
print('Hi') | |
end | |
--[[新增一個table 裡面塞入一個function 和 string | |
這邊f就是key,對應的value就是func這個函數 | |
這邊name就是key,對應的value就是iris這個字串 ]] | |
local aTable = {f = func, name = "iris"} | |
-- 在table.後面加入key就可以直接使用table中的內容 | |
aTable.f() | |
print(aTable.name) | |
輸出結果如下
Hi
iris
Multiple Assignment
這個用法挺方便的,假如我有一個座標是(3,5) 程式碼就能寫成 x,y = 3,5 這樣x就被給予3這個值, y就被給予5這個值,如果同時要assign相同類型的變數,可以用這個方法,下面有個簡單的範例
local function Point(x, y) | |
return { | |
x = x, | |
y = y | |
} | |
end | |
-- 寫個table 定義兩個點座標 | |
local array = {Point(3, 5), Point(4, 4)} | |
for k, v in pairs(array) do | |
-- 這邊x = v.x, y=v.y | |
local x, y = v.x, v.y | |
print(x .. ' ' .. y) | |
end | |
輸出結果如下
3 5
4 4
Function
前面的範例就有用到簡單的function, 而function 的回傳值就用到multi-assignment的概念
那這個範例順便包含了字串的處理,也有提到在字串處理常使用到正規表示式,相對而言比較方便的語法
--[[ 這個function 是用來分割字串的 | |
將字串一單詞分割,並存入table | |
回傳單詞個數和table | |
]] | |
function splitStr(theString) | |
stringTable = {} | |
local i = 1 | |
-- Lua在字串比對的時候是使用Regular Expression(正規表示式) 例如[^是字串開頭、$是句子結尾...等用法 | |
for word in string.gmatch(theString, "[^%s]+") do | |
stringTable[i] = word | |
i = i + 1 | |
end | |
-- 這邊回傳兩個變數 | |
return stringTable, i | |
end | |
-- 因為回傳兩個變數,所以我們需要用兩個變數來接收 | |
splitStrTable, numOfStr = splitStr("She is a girl") | |
-- 把所有單詞印出來 | |
for j = 1, numOfStr do | |
print(string.format("%d: %s", j, splitStrTable[j])) | |
end | |
輸出結果如下
1: She
2: is
3: a
4: girl
5: nil
Module
Module 中文式模塊的意思,他可以用require() 呼叫的library,並且具有包含表的單個全局名稱
該模塊可以包含許多功能和變量。所有這些函數和變量都包裝在表中,該表用作名稱空間。
前面這些太難懂了,簡單來說 Module就是一個table
寫一個module的方法如下
-- 先新增一個table | |
Engineer = {} | |
-- 我們可以在table中放入一個string | |
Engineer.Type = "BMC" | |
-- 當然也可以放入一個function | |
-- 這邊sayHi(...)的意思是可以傳入任何變數的意思 | |
function Engineer.sayHi(...) | |
print("Hello World!") | |
end | |
-- 最後回傳一個table | |
return Engineer |
這邊就能很簡單的理解module就是一個table,那要在另外一隻檔案中引用它也很簡單
-- 這邊engineer 就可以看成一個table | |
local engineer = require("test") | |
-- 可以用module中的各種變數或函數 | |
engineer.sayHi() | |
print(engineer.Type) |
輸出結果如下
Hello World!
BMC
感谢很好的入门教程
回覆刪除用的lua 5.3
最后一个return Engineer lua总是报错
看起来和文档的example 没差
https://www.tutorialspoint.com/lua/lua_modules.htm
模仿spx code 去写就没什么问题不过看起来结构不太一样:
function module()
-- 先新增一個table
local module_table = {}
module_table.Type = "BMC"
function module_table.sayHi(...)
print("Hello World!")
end
return module_table
end
-- 這邊engineer 就可以看成一個table
local container = module()
-- 可以用module中的各種變數或函數
container.sayHi()
print(container.Type)
eyer@mega1:~/lab$ lua eyer.lua
Hello World!
BMC