Loading [MathJax]/extensions/TeX/AMSsymbols.js

2021年5月6日 星期四

10分鐘學會Lua Basics ( Multiple Assignment, Table, Module, Function )

這是一篇文章能讓你10 分鐘學會lua 基本用法的教學文

底下是這篇文章會介紹到的基本用法,灰色部分會在其他章節中另外介紹

Lua Basics

Comment

String

Number

Variable scope

Ternary Operator

Loop Activity(while, repeat)

Table

Multiple Assignment

Function

Module 

Coroutines(點我)

Metatables

Prototype Based OO Programming

LuaJIT - FFI Library


以下會用各種範例來和大家介紹lua有哪些功能和用法,知道這些用法之後,遇到不懂的語法也能知道怎麼搜尋關鍵字 


#Lua Basic


Comment


註解用--表示,多行可以用兩個中括號包起來

-- comment
--[[ 
    multiline 
]]
view raw comment.lua hosted with ❤ by GitHub


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)
view raw comment.lua hosted with ❤ by GitHub

輸出結果如下

Size of string is 4

I am a long long long long
        long
......string ~
Iris+I am a long long long long
        long
......string ~


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)
view raw lua.lua hosted with ❤ by GitHub

輸出結果如下

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'))
view raw lua.lua hosted with ❤ by GitHub

輸出結果如下

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
view raw lua.lua hosted with ❤ by GitHub

輸出結果如下

i= 1

end

i= 2

continue

i= 3

break


repeat

value = 3
repeat 
    print('value is: ' .. value) 
value = value - 1
-- 直到符合until中的條件才會離開迴圈
until (value < 0)
view raw lua.lua hosted with ❤ by GitHub

輸出結果如下

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)
view raw table-1.lua hosted with ❤ by GitHub

輸出結果如下

(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)
view raw lua.lua hosted with ❤ by GitHub


輸出結果如下

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
view raw Function.lua hosted with ❤ by GitHub

輸出結果如下

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
view raw Module1.lua hosted with ❤ by GitHub

這邊就能很簡單的理解module就是一個table,那要在另外一隻檔案中引用它也很簡單

-- 這邊engineer 就可以看成一個table
local engineer = require("test")
-- 可以用module中的各種變數或函數
engineer.sayHi()
print(engineer.Type)
view raw Module2.lua hosted with ❤ by GitHub

輸出結果如下

Hello World!

BMC


基礎語法介紹到這邊就差不多了,大家學廢了嗎😏


1 則留言:

  1. 感谢很好的入门教程
    用的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

    回覆刪除

注意:只有此網誌的成員可以留言。