開發與維運

Lua 基礎

【轉載請註明出處】:https://developer.aliyun.com/article/758555

基本語法

註釋
  • 兩個減號是單行註釋:
    --註釋
  • 多行註釋
    `--[[ 註釋 --]]

`

標示符

標示符以字母或下劃線 _ 開頭,加上字母、下劃線或數字組成。
最好不要使用下劃線加大寫字母的標示符,因為Lua的保留字也是這樣的。

關鍵詞

以下列出了 Lua 的保留關鍵字。保留關鍵字不能作為常量或變量或其他用戶自定義標示符:
and 、break 、 do 、 else 、 elseif 、end、false 、for 、 function 、if 、in 、 local 、nil 、 not 、 or 、 repeat 、return 、 then 、true 、until 、while
一般約定,以下劃線開頭連接一串大寫字母的名字(比如 _VERSION)被保留用於 Lua 內部全局變量。

全局變量

在默認情況下,變量總是認為是全局的。

Lua 數據類型

Lua中有8個基本類型分別為:nil、boolean、number、string、userdata、function、thread和table。
| 數據類型 | 描述 | 說明 |
| - | - | - |
| nil | 這個最簡單,只有值nil屬於該類,表示一個無效值(在條件表達式中相當於false)。| nil 作比較時應該加上雙引號 |
| boolean | 包含兩個值:false和true。| Lua 把 false 和 nil 看作是"假",其他的都為"真" |
| number | 表示雙精度類型的實浮點數 | |
| string | 字符串由一對雙引號或單引號來表示 | 也可以用 2 個方括號 "[[]]" 來表示"一塊"字符串。
使用 # 來計算字符串的長度
在對一個數字字符串上進行算術操作時,Lua 會嘗試將這個數字字符串轉成一個數字|
| function | 由 C 或 Lua 編寫的函數 | |
| userdata | 表示任意存儲在變量中的C數據結構 | |
| thread | 表示執行的獨立線路,用於執行協同程序 | |
| table | Lua 中的表(table)其實是一個"關聯數組"(associative arrays),數組的索引可以是數字或者是字符串。在 Lua 裡,table 的創建是通過"構造表達式"來完成,最簡單構造表達式是{},用來創建一個空表。 | |

可以使用type函數測試給定變量或者值的類型。

Lua 變量

Lua 變量有三種類型:全局變量、局部變量、表中的域。
Lua 中的變量全是全局變量,那怕是語句塊或是函數裡,除非用 local 顯式聲明為局部變量。
局部變量的作用域為從聲明位置開始到所在語句塊結束。

賦值語句
--賦值是改變一個變量的值和改變表域的最基本的方法。
a = "hello" .. "world"
t.n = t.n + 1

--Lua可以對多個變量同時賦值,變量列表和值列表的各個元素用逗號分開,賦值語句右邊的值會依次賦給左邊的變量。
a, b = 10, 2*x     -- 等價於  a=10; b=2*x

當變量個數和值的個數不一致時,Lua會一直以變量個數為基礎採取以下策略:

  • 變量個數 > 值的個數 按變量個數補足nil
  • 變量個數 < 值的個數 多餘的值會被忽略
索引

對 table 的索引使用方括號 []。Lua 也提供了 . 操作。

t[i]
t.i     -- 當索引為字符串類型時的一種簡化寫法

Lua 循環

Lua 語言提供了以下幾種循環處理方式:

| 循環類型 | 描述 |
| - | - |
| while 循環 |在條件為 true 時,讓程序重複地執行某些語句。執行語句前會先檢查條件是否為 true。 |
| for 循環| 重複執行指定語句,重複次數可在 for 語句中控制。 |
| repeat...until| 重複執行循環,直到 指定的條件為真時為止 |
| 循環嵌套 | 可以在循環內嵌套一個或多個循環語句(while do ... end;for ... do ... end;repeat ... until;) |

while 循環
while(condition)
do
   statements
end
數值for循環

Lua 編程語言中數值for循環語法格式:

for var=exp1,exp2,exp3 do  
    statements
end  

var 從 exp1 變化到 exp2,每次變化以 exp3 為步長遞增 var,並執行一次 "執行體"。exp3 是可選的,如果不指定,默認為1。

泛型for循環

泛型 for 循環通過一個迭代器函數來遍歷所有值,類似 java 中的 foreach 語句。

for i, v in ipairs(value) do
     statements
end 

i是數組索引值,v是對應索引的數組元素值。ipairs是Lua提供的一個迭代器函數,用來迭代數組。

repeat...until 循環
repeat
   statements
until( condition )

Lua 流程控制

Lua 提供了以下控制結構語句:
| 語句 | 描述 |
| - | - |
| if 語句| if 語句 由一個布爾表達式作為條件判斷,其後緊跟其他語句組成。 |
| if...else 語句 | if 語句 可以與 else 語句搭配使用, 在 if 條件表達式為 false 時執行 else 語句代碼。 |
| if 嵌套語句| 你可以在if 或 else if中使用一個或多個 if 或 else if 語句 。 |

if 語句
if(condition)
then
   statements
end
if...else 語句
if(condition)
then
  statements1
else
   statements2
end
if...elseif...else 語句
if(condition1)
then
  statements1
elseif(condition2) 
then
   statements2
else 
   statements3
end

Lua 函數

函數定義
optional_function_scope function function_name( argument1, argument2, argument3..., argumentn)
    function_body
    return result_params_comma_separated
end
  • optional_function_scope: 該參數是可選的制定函數是全局函數還是局部函數,未設置該參數默認為全局函數,如果你需要設置函數為局部函數需要使用關鍵字 local。
  • function_name: 指定函數名稱。
  • argument1, argument2, argument3..., argumentn: 函數參數,多個參數以逗號隔開,函數也可以不帶參數。
  • function_body: 函數體,函數中需要執行的代碼語句塊。
  • result_params_comma_separated: 函數返回值,Lua語言函數可以返回多個值,每個值以逗號隔開。
多返回值

Lua函數中,在return後列出要返回的值的列表即可返回多值。

可變參數

Lua 函數可以接受可變數目的參數,和 C 語言類似,在函數參數列表中使用三點 ... 表示函數有可變的參數。
有時候可能需要幾個固定參數加上可變參數,則固定參數必須放在變長參數之前。
通常在遍歷變長參數的時候只需要使用 {…},然而變長參數可能會包含一些 nil,那麼就可以用 select 函數來訪問變長參數了:select('#', …) 或者 select(n, …)

  • select('#', …) 返回可變參數的長度
  • select(n, …) 返回它的第n個可變實參
function average(...)
   result = 0
   local arg={...}    
   for i,v in ipairs(arg) do
      result = result + v
   end 
   return result/#arg    --或者 return result/select("#",...)
end

Lua 運算符

算術運算符

| 操作符 | 描述 |
| - | - |
| + | 加法 |
| - | 減法/負號 |
| * | 乘法 |
| / | 除法 |
| % | 取餘 |
| ^ | 乘冪 |

關係運算符

| 操作符 | 描述 |
| - | - |
| == |等於,檢測兩個值是否相等,相等返回 true,否則返回 false |
| ~= | 不等於,檢測兩個值是否相等,相等返回 false,否則返回 true |
| > | 大於,如果左邊的值大於右邊的值,返回 true,否則返回 false |
| < | 小於,如果左邊的值大於右邊的值,返回 false,否則返回 true |
| >= | 大於等於,如果左邊的值大於等於右邊的值,返回 true,否則返回 false |
| <= | 小於等於, 如果左邊的值小於等於右邊的值,返回 true,否則返回 false|

邏輯運算符

| 操作符 | 描述 |
| - | - |
| and |邏輯與操作符。|
| or | 邏輯或操作符。|
| not | 邏輯非操作符。|

其他運算符

|操作符 | 描述 |
| - | - |
| .. | 連接兩個字符串 |
| # | 一元運算符,返回字符串或表的長度。 |

運算符優先級

|從高到低的順序|
| - |
| ^ |
| not - (unary) |
| * / |
| + - |
| .. |
| < > <= >= ~= == |
| and |
| or |
除了^和..外所有的二元運算符都是左連接的。

Lua 字符串

Lua 語言中字符串可以使用以下三種方式來表示:

  • 單引號間的一串字符。
  • 雙引號間的一串字符。
  • [[和]]間的一串字符。
字符串操作

| 方法 | 用途 |
| - | - |
| string.upper(argument) | 全部轉為大寫 |
| string.lower(argument) | 全部轉為小寫 |
| string.gsub(mainString,findString,replaceString,num) |在字符串中替換,mainString為要替換的字符串, findString 為被替換的字符,replaceString 要替換成的字符,num 替換次數(可以忽略,則全部替換)|
| string.find (mainString, findString, [startIndex, [endIndex]]) | 在一個指定的目標字符串中搜索指定的內容(第三個參數為索引),返回其具體位置。不存在則返回 nil。|
| string.reverse(arg) | 字符串反轉 |
| string.format(...) | 返回一個類似printf的格式化字符串 |
| string.char(ASCIICodes...) | 將ASCII碼轉成字符並連接|
| string.byte(str[,index]) | 將指定的字符轉成ASCII碼(默認第一個字符)|
| string.len(arg) | 計算字符串長度 |
| string.rep(str, n) | 返回字符串string的n個拷貝 |
| .. | 鏈接兩個字符串 |
| string.gmatch(str, pattern) | 返回一個迭代器函數,每一次調用這個函數,返回一個在字符串 str 找到的下一個符合 pattern 描述的子串。如果參數 pattern 描述的字符串沒有找到,迭代函數返回nil。|
|string.match(str, pattern, init) | string.match()只尋找源字串str中的第一個配對. 參數init可選, 指定搜尋過程的起點, 默認為1。
在成功配對時, 函數將返回配對表達式中的所有捕獲結果; 如果沒有設置捕獲標記, 則返回整個配對字符串. 當沒有成功的配對時, 返回nil。 |

Lua 數組

Lua 數組的索引鍵值可以使用整數表示,數組的大小不是固定的。
可以使用整數索引來訪問數組元素,如果指定的索引沒有值則返回nil。
Lua 索引值是以 1 為起始,但也可以指定 0 開始,除此之外還可以以負數為數組索引值。

Lua 迭代器

迭代器(iterator)是一種對象,它能夠用來遍歷標準模板庫容器中的部分或全部元素,每個迭代器對象代表容器中的確定的地址
在Lua中迭代器是一種支持指針類型的結構,它可以遍歷集合的每一個元素。

泛型 for 迭代器

泛型 for 在自己內部保存迭代函數,實際上它保存三個值:迭代函數、狀態常量、控制變量。
泛型 for 迭代器提供了集合的 key/value 對,語法格式如下:

for k, v in pairs(t) do
    print(k, v)
end

k, v為變量列表;pairs(t)為表達式列表。

Lua 的迭代器包含以下兩種類型:
無狀態的迭代器

無狀態的迭代器是指不保留任何狀態的迭代器,因此在循環中可以利用無狀態迭代器避免創建閉包花費額外的代價。
每一次迭代,迭代函數都是用兩個變量(狀態常量和控制變量)的值作為參數被調用,一個無狀態的迭代器只利用這兩個值可以獲取下一個元素。

例如使用一個簡單的函數來實現迭代器,實現數字 n 的平方:

function square(iteratorMaxCount,currentNumber)
   if currentNumber<iteratorMaxCount
   then
      currentNumber = currentNumber+1
   return currentNumber, currentNumber*currentNumber
   end
end

for i,n in square,3,0
do
   print(i,n)
end
多狀態的迭代器

很多情況下,迭代器需要保存多個狀態信息而不是簡單的狀態常量和控制變量,最簡單的方法是使用閉包,還有一種方法就是將所有的狀態信息封裝到table內,將table作為迭代器的狀態常量,因為這種情況下可以將所有的信息存放在table內,所以迭代函數通常不需要第二個參數。

例如:

function elementIterator (collection)
   local index = 0
   local count = #collection
   -- 閉包函數
   return function ()
      index = index + 1
      if index <= count
      then
         --  返回迭代器的當前元素
         return collection[index]
      end
   end
end

array = {"Lua", "Tutorial"}
for element in elementIterator(array)
do
   print(element)
end

Lua table(表)

table 是 Lua 的一種數據結構用來幫助我們創建不同的數據類型,如:數組、字典等。
Lua table 使用關聯型數組,可以用任意類型的值來作數組的索引,但這個值不能是 nil。
Lua table 是不固定大小的,可以根據自己需要進行擴容。
Lua也是通過table來解決模塊(module)、包(package)和對象(Object)的。 例如string.format表示使用"format"來索引table string。

| 方法 | 用途 |
| - | - |
| table.concat (tableObj [, separator [, startIndex [, endIndex]]]) | 列出tableObj從startIndex位置到endIndex位置的所有元素, 元素間以指定的分隔符(separator)隔開。|
| table.insert (tableObj, [index,] value) | 在tableObj的指定位置(index)插入值為value的一個元素。index參數可選, 默認為末尾。 |
| table.remove (tableObj [, index]) | 返回tableObj位於index位置的元素。 其後的元素會被前移。index參數可選, 默認為table長度, 即從最後一個元素刪起。 |
| table.sort (tableObj [, comp]) | 對給定的table進行升序排序。comp應滿足以下條件: 接受兩個參數(依次為a, b), 並返回一個布爾型的值, 當a應該排在b前面時, 返回true, 反之返回false. |

【轉載請註明出處】:https://developer.aliyun.com/article/758555

Leave a Reply

Your email address will not be published. Required fields are marked *