Lua5.3學習筆記

xbynet發表於2016-12-22

Lua 是一門強大、輕量的嵌入式指令碼語言,可供任何需要的程式使用。Lua 沒有 “main” 程式的概念: 它只能 嵌入 一個宿主程式中工作.宿主程式可以呼叫函式執行一小段 Lua 程式碼,可以讀寫 Lua 變數,可以註冊 C 函式讓 Lua 程式碼呼叫。
Lua 是一門動態型別語言。 這意味著變數沒有型別;只有值才有型別。
Lua 中所有的值都是 一等公民。 這意味著所有的值均可儲存在變數中、 當作引數傳遞給其它函式、以及作為返回值。
文件:5.3:http://cloudwu.github.io/lua5…
5.1:http://book.luaer.cn/

基礎

八種基本型別

Lua 中有八種基本型別: nil、boolean、number、string、function、userdata、 thread 和 table。
Nil 是值 nil 的型別.和Python中None,Java中null類似。
Boolean 是 false 與 true 兩個值的型別。與其他語言不通的是nil 和 false 都會導致條件判斷為假; 而其它任何值都表示為真。而其它語言判斷比如0時為假,但lua為真。
Number 代表了整數和實數(浮點數)。 它也按需作自動轉換
String 表示一個不可變的位元組序列。Lua 的字串與編碼無關; 它不關心字串中具體內容。
Lua 可以呼叫(以及操作)用 Lua 或 C 編寫的函式。 這兩種函式有統一型別 function
userdata 型別允許將 C 中的資料儲存在 Lua 變數中。 使用者資料型別的值是一個記憶體塊, 有兩種使用者資料: 完全使用者資料 ,指一塊由 Lua 管理的記憶體對應的物件; 輕量使用者資料 ,則指一個簡單的 C 指標。 使用者資料在 Lua 中除了賦值與相等性判斷之外沒有其他預定義的操作。 通過使用 元表 ,程式設計師可以給完全使用者資料定義一系列的操作。 你只能通過 C API 而無法在 Lua 程式碼中建立或者修改使用者資料的值, 這保證了資料僅被宿主程式所控制。
thread 型別表示了一個獨立的執行序列,被用於實現協程Lua 的執行緒與作業系統的執行緒毫無關係。 Lua 為所有的系統,包括那些不支援原生執行緒的系統,提供了協程支援
table 是一個關聯陣列, 也就是說,這個陣列不僅僅以數字做索引,除了 nil 和 NaN 之外的所有 Lua 值 都可以做索引。(Not a Number 是一個特殊的數字,它用於表示未定義或表示不了的運算結果,比如 0/0。) 表可以是 異構 的; 也就是說,表內可以包含任何型別的值( nil 除外)。
表是 Lua 中唯一的資料結構, 它可被用於表示普通陣列、序列、符號表、集合、記錄、圖、樹等等。 對於記錄,Lua 使用域名作為索引。 語言提供了 a.name 這樣的語法糖來替代 a[“name”]。
我們使用 序列 這個術語來表示一個用 {1..n} 的正整數集做索引的表.注意:lua中索引從1開始,而非0
和索引一樣,表中每個域的值也可以是任何型別。 需要特別指出的是:既然函式是一等公民,那麼表的域也可以是函式。 這樣,表就可以攜帶 方法 了。

表、函式、執行緒、以及完全使用者資料在 Lua 中被稱為 物件: 變數並不真的 持有 它們的值,而僅儲存了對這些物件的 引用。 賦值、引數傳遞、函式返回,都是針對引用而不是針對值的操作, 這些操作均不會做任何形式的隱式拷貝。

型別判斷

庫函式 type 用於以字串形式返回給定值的型別。

錯誤處理

由於 Lua 是一門嵌入式擴充套件語言,其所有行為均源於宿主程式中 C 程式碼對某個 Lua 庫函式的呼叫。 (單獨使用 Lua 時,lua 程式就是宿主程式。) 所以,在編譯或執行 Lua 程式碼塊的過程中,無論何時發生錯誤, 控制權都返回給宿主,由宿主負責採取恰當的措施(比如列印錯誤訊息)。
可以在 Lua 程式碼中呼叫 error 函式來顯式地丟擲一個錯誤。 如果你需要在 Lua 中捕獲這些錯誤, 可以使用 pcall 或 xpcall 在 保護模式 下呼叫一個函式。
無論何時出現錯誤,都會丟擲一個攜帶錯誤資訊的 錯誤物件 (錯誤訊息),這是一個字串物件。
使用 xpcall 或 lua_pcall 時, 你應該提供一個 訊息處理函式 用於錯誤丟擲時呼叫。 該函式需接收原始的錯誤訊息,並返回一個新的錯誤訊息。

元表及元方法

Lua 中的每個值都可以有一個 元表。 這個 元表 就是一個普通的 Lua 表, 它用於定義原始值在特定操作下的行為。元表中的鍵對應著不同的 事件 名; 鍵關聯的那些值被稱為 元方法。
你可以用 getmetatable 函式 來獲取任何值的元表。
使用 setmetatable 來替換一張表的元表。在 Lua 中,你不可以改變表以外其它型別的值的元表 (除非你使用除錯庫); 若想改變這些非表型別的值的元表,請使用 C API。
表和完全使用者資料有獨立的元表 (當然,多個表和使用者資料可以共享同一個元表)。 其它型別的值按型別共享元表; 也就是說所有的數字都共享同一個元表, 所有的字串共享另一個元表等等。
元表決定了一個物件在數學運算、位運算、比較、連線、 取長度、呼叫、索引時的行為。 元表還可以定義一個函式,當表物件或使用者資料物件在垃圾回收時呼叫它。
其它具體見文件。。。。

垃圾收集

Lua 採用了自動記憶體管理。Lua 實現了一個增量標記-掃描收集器。
垃圾收集元方法:
你可以為表設定垃圾收集的元方法,對於完全使用者資料, 則需要使用 C API 。 該元方法被稱為 終結器。 終結器允許你配合 Lua 的垃圾收集器做一些額外的資源管理工作 (例如關閉檔案、網路或資料庫連線,或是釋放一些你自己的記憶體)。
如果要讓一個物件(表或使用者資料)在收集過程中進入終結流程, 你必須 標記 它需要觸發終結器。 當你為一個物件設定元表時,若此刻這張元表中用一個以字串 “__gc” 為索引的域,那麼就標記了這個物件需要觸發終結器。

協程

呼叫函式 coroutine.create 可建立一個協程。 其唯一的引數是該協程的主函式。 create 函式只負責新建一個協程並返回其控制程式碼 (一個 thread 型別的物件); 而不會啟動該協程。

呼叫 coroutine.resume 函式執行一個協程。
協程的執行可能被兩種方式終止: 正常途徑是主函式返回 (顯式返回或執行完最後一條指令); 非正常途徑是發生了一個未被捕獲的錯誤。 對於正常結束, coroutine.resume 將返回 true, 並接上協程主函式的返回值。 當錯誤發生時, coroutine.resume 將返回 false 與錯誤訊息。

通過呼叫 coroutine.yield 使協程暫停執行,讓出執行權。 協程讓出時,對應的最近 coroutine.resume 函式會立刻返回,即使該讓出操作發生在內嵌函式呼叫中 (即不在主函式,但在主函式直接或間接呼叫的函式內部)。 在協程讓出的情況下, coroutine.resume 也會返回 true, 並加上傳給 coroutine.yield 的引數。 當下次重啟同一個協程時, 協程會接著從讓出點繼續執行。

與 coroutine.create 類似, coroutine.wrap 函式也會建立一個協程。 不同之處在於,它不返回協程本身,而是返回一個函式。 呼叫這個函式將啟動該協程。 傳遞給該函式的任何引數均當作 coroutine.resume 的額外引數。 coroutine.wrap 返回 coroutine.resume 的所有返回值,除了第一個返回值(布林型的錯誤碼)。 和 coroutine.resume 不同, coroutine.wrap 不會捕獲錯誤; 而是將任何錯誤都傳播給呼叫者。

下面的程式碼展示了一個協程工作的範例:

     function foo (a)
       print("foo", a)
       return coroutine.yield(2*a)
     end
     
     co = coroutine.create(function (a,b)
           print("co-body", a, b)
           local r = foo(a+1)
           print("co-body", r)
           local r, s = coroutine.yield(a+b, a-b)
           print("co-body", r, s)
           return b, "end"
     end)
     
     print("main", coroutine.resume(co, 1, 10))
     print("main", coroutine.resume(co, "r"))
     print("main", coroutine.resume(co, "x", "y"))
     print("main", coroutine.resume(co, "x", "y"))
當你執行它,將產生下列輸出:

     co-body 1       10
     foo     2
     main    true    4
     co-body r
     main    true    11      -9
     co-body x       y
     main    true    10      end
     main    false   cannot resume dead coroutine

你也可以通過 C API 來建立及操作協程: 參見函式 lua_newthread, lua_resume, 以及 lua_yield。

語言定義

Lua 語言的格式自由。 它會忽略語法元素(符記)間的空格(包括換行)和註釋, 僅把它們看作為名字和關鍵字間的分割符。
Lua 語言對大小寫敏感。
字面串 可以用單引號或雙引號括起。 字面串內部可以包含下列 C 風格的轉義串。
轉義串 `z` 會忽略其後的一系列空白符,包括換行; 它在你需要對一個很長的字串常量斷行為多行並希望在每個新行保持縮排時非常有用。
對於用 UTF-8 編碼的 Unicode 字元,你可以用 轉義符 u{XXX} 來表示

程式碼註釋:

--這是行註釋
--[[這是塊
註釋]]

變數:

Lua 中有三種變數: 全域性變數、區域性變數和表的域。
所有沒有顯式宣告為區域性變數的變數名都被當做全域性變數 這一點倒是和js很相似。
全域性變數 x = 1234 的賦值等價於 _ENV.x = 1234
區域性變數 local namelist [‘=’ explist] 比如 local name=`xbynet`

語句:

每個語句結尾的分號(;)是可選的,但如果同一行有多個語句最好用;分開

-- file `lib1.lua`
 
function norm (x, y)
    local n2 = x^2 + y^2
    return math.sqrt(n2)
end
 
function twice (x)
    return 2*x
end

在互動模式下:

> lua -i 
> dofile("lib1.lua")     -- load your library
> n = norm(3.4, 1.0)
> print(twice(n))        --> 7.0880180586677

-i和dofile在除錯或者測試Lua程式碼時是很方便的。

命令列方式

> lua -e "print(math.sin(12))"   --> -0.53657291800043

全域性變數arg存放Lua的命令列引數。
prompt> lua script a b c
在執行以前,Lua使用所有引數構造arg表。指令碼名索引為0,指令碼的引數從1開始增加。指令碼前面的引數從-1開始減少。

if, while, and repeat 這些控制結構符合通常的意義,而且也有類似的語法:

while exp do block end
repeat block until exp
if exp then block elseif exp then block else block end

for 有兩種形式:一種是數字形式,另一種是通用形式。
數值for迴圈:

for var=exp1,exp2,exp3 do
    loop-part
end

for將用exp3作為step從exp1(初始值)到exp2(終止值),執行loop-part。其中exp3可以省略,預設step=1
有幾點需要注意:

  1. 三個表示式只會被計算一次,並且是在迴圈開始前。

    for i=1,f(x) do

    print(i)

    end

    for i=10,1,-1 do

    print(i)

    end

第一個例子f(x)只會在迴圈前被呼叫一次

通用形式的 for 通過一個叫作 迭代器 的函式工作。 每次迭代,迭代器函式都會被呼叫以產生一個新的值, 當這個值為 nil 時,迴圈停止

for var_1, ···, var_n in explist do block end

-- print all values of array `a`
for i,v in ipairs(a) do print(v) end

再看一個遍歷表key的例子:
-- print all keys of table `t`
for k in pairs(t) do print(k) end  
 

控制結構中的條件表示式可以返回任何值。 false 與 nil 兩者都被認為是假。 所有不同於 nil 與 false 的其它值都被認為是真 (特別需要注意的是,數字 0 和空字串也被認為是真)。
有break,但是沒有continue
return 被用於從函式或是程式碼塊(其實它就是一個函式) 中返回值。 函式可以返回不止一個值。
return 只能被寫在一個語句塊的最後一句。 如果你真的需要從語句塊的中間 return, 你可以使用顯式的定義一個內部語句塊, 一般寫作 do return end。 可以這樣寫是因為現在 return 成了(內部)語句塊的最後一句了。

Lua語法要求break和return只能出現在block的結尾一句(也就是說:作為chunk的最後一句,或者在end之前,或者else前,或者until前),例如:

local i = 1
while a[i] do
    if a[i] == v then break end
    i = i + 1
end

有時候為了除錯或者其他目的需要在block的中間使用return或者break,可以顯式的使用do..end來實現:

function foo ()
    return            --<< SYNTAX ERROR
    -- `return` is the last statement in the next block
    do return end        -- OK
    ...               -- statements not reached
end

表示式

數學運算操作符

+: 加法
-: 減法
*: 乘法
/: 浮點除法
//: 向下取整除法
%: 取模
^: 乘方
-: 取負

比較操作符

==: 等於
~=: 不等於
<: 小於
>: 大於
<=: 小於等於
>=: 大於等於

注意:不等於是~=,而不是!=
這些操作的結果不是 false 就是 true。
等於操作 (==)先比較運算元的型別。 如果型別不同,結果就是 false。 否則,繼續比較值。 字串按一般的方式比較。 數字遵循二元操作的規則
表,使用者資料,以及執行緒都按引用比較: 只有兩者引用同一個物件時才認為它們相等。
你可以通過使用 “eq” 元方法來改變 Lua 比較表和使用者資料時的方式。

邏輯操作符
Lua 中的邏輯操作符有 and, or,以及 not
和控制結構一樣, 所有的邏輯操作符把 false 和 nil 都作為假, 而其它的一切都當作真。

字串連線
Lua 中字串的連線操作符寫作兩個點(`..`)。 如果兩個運算元都是字串或都是數字, 連線操作將以中提到的規則把其轉換為字串。 否則,會呼叫元方法 __concat
多行字串
還可以使用[[…]]表示字串。這種形式的字串可以包含多行

page = [[
qwwqwq
adas
ss
]]

取長度操作符
取長度操作符寫作一元前置符 #。 字串的長度是它的位元組數(就是以一個字元一個位元組計算的字串長度)。而Python是內建的len()函式,Java和JS都是字串函式.length()
程式可以通過 __len 元方法來修改對字串型別外的任何值的取長度操作行為。

表構建

表構造子是一個構造表的表示式。 每次構造子被執行,都會構造出一張新的表。 構造子可以被用來構造一張空表, 也可以用來構造一張表並初始化其中的一些域。
構造器是建立和初始化表的表示式。表是Lua特有的功能強大的東西。最簡單的建構函式是{},用來建立一個空表。可以直接初始化陣列:

days = {"Sunday", "Monday", "Tuesday", "Wednesday",
              "Thursday", "Friday", "Saturday"}

Lua將”Sunday”初始化days[1](第一個元素索引為1),用”Monday”初始化days[2]…
如果想初始化一個表作為record使用可以這樣:

a = {x=0, y=0}       <-->       a = {}; a.x=0; a.y=0

不管用何種方式建立table,我們都可以向表中新增或者刪除任何型別的域,建構函式僅僅影響表的初始化。

w = {x=0, y=0, label="console"}
x = {sin(0), sin(1), sin(2)}
w[1] = "another field"
x.f = w
print(w["x"])     --> 0
print(w[1])       --> another field
print(x.f[1])     --> another field
w.x = nil         -- remove field "x"

值得注意的是:w.x = nil — remove field “x”

在建構函式中域分隔符逗號(”,”)可以用分號(”;”)替代,通常我們使用分號用來分割不同型別的表元素。

{x=10, y=45; "one", "two", "three"}

舉個例子:

a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 }

等價於

 do
   local t = {}
   t[f(1)] = g
   t[1] = "x"         -- 1st exp
   t[2] = "y"         -- 2nd exp
   t.x = 1            -- t["x"] = 1
   t[3] = f(x)        -- 3rd exp
   t[30] = 23
   t[4] = 45          -- 4th exp
   a = t
 end

如果表單中最後一個域的形式是 exp , 而且其表示式是一個函式呼叫或者是一個可變引數, 那麼這個表示式所有的返回值將依次進入列表

函式

函式定義

 function f () body end
 local function f () body end
 

當一個函式被呼叫, 如果函式並非一個 可變引數函式, 即在形參列表的末尾註明三個點 (`...`), 那麼實參列表就會被調整到形參列表的長度。

     function f(a, b) end
     function g(a, b, ...) end
     function r() return 1,2,3 end

下面看看實參到形引數以及可變長引數的對映關係:

 CALL            PARAMETERS
 
 f(3)             a=3, b=nil
 f(3, 4)          a=3, b=4
 f(3, 4, 5)       a=3, b=4
 f(r(), 10)       a=1, b=10
 f(r())           a=1, b=2
 
 g(3)             a=3, b=nil, ... -->  (nothing)
 g(3, 4)          a=3, b=4,   ... -->  (nothing)
 g(3, 4, 5, 8)    a=3, b=4,   ... -->  5  8
 g(5, r())        a=5, b=1,   ... -->  2  3
 

冒號 語法可以用來定義 方法, 就是說,函式可以有一個隱式的形參 self。 因此,如下語句

 function t.a.b.c:f (params) body end

是這樣一種寫法的語法糖

 t.a.b.c.f = function (self, params) body end

Lua函式可以返回多個結果值

function maximum (a)
    local mi = 1             -- maximum index
    local m = a[mi]          -- maximum value
    for i,val in ipairs(a) do
       if val > m then
           mi = i
           m = val
       end
    end
    return m, mi
end
 
print(maximum({8,10,23,12,5}))     --> 23   3

Lua總是調整函式返回值的個數以適用呼叫環境,當作為獨立的語句呼叫函式時,所有返回值將被忽略
第一,當作為表示式呼叫函式時,有以下幾種情況:

  1. 當呼叫作為表示式最後一個引數或者僅有一個引數時,根據變數個數函式儘可能多地返回多個值,不足補nil,超出捨去。

  2. 其他情況下,函式呼叫僅返回第一個值(如果沒有返回值為nil)
    第二,函式呼叫作為函式引數被呼叫時,和多值賦值是相同。

第三,函式呼叫在表建構函式中初始化時,和多值賦值時相同。

可變引數與命名引數

printResult = ""
 
function print(...)
    for i,v in ipairs(arg) do
       printResult = printResult .. tostring(v) .. "	"
    end
    printResult = printResult .. "
"
end

命名引數用表來作為引數傳遞。

可見性規則

Lua 語言有詞法作用範圍。 變數的作用範圍開始於宣告它們之後的第一個語句段, 結束於包含這個宣告的最內層語句塊的最後一個非空語句。

     x = 10                -- 全域性變數
     do                    -- 新的語句塊
       local x = x         -- 新的一個 `x`, 它的值現在是 10
       print(x)            --> 10
       x = x+1
       do                  -- 另一個語句塊
         local x = x+1     -- 又一個 `x`
         print(x)          --> 12
       end
       print(x)            --> 11
     end
     print(x)              --> 10 (取到的是全域性的那一個)

區域性變數可以被在它的作用範圍內定義的函式自由使用。 當一個區域性變數被內層的函式中使用的時候, 它被內層函式稱作 上值,或是 外部區域性變數

注意,每次執行到一個 local 語句都會定義出一個新的區域性變數。 看看這樣一個例子:

 a = {}
 local x = 20
 for i=1,10 do
   local y = 0
   a[i] = function () y=y+1; return x+y end
 end

這個迴圈建立了十個閉包(這指十個匿名函式的例項)。 這些閉包中的每一個都使用了不同的 y 變數, 而它們又共享了同一份 x。

C API介面

由於,目前關注重點在於簡單的redis與Lua及nginx與lua互動,故而暫時略去此部分學習。。。

標準庫

所有的庫都是直接用 C API 實現的,並以分離的 C 模組形式提供。 目前,Lua 有下列標準庫:
基礎庫
協程庫
包管理庫
字串控制
基礎 UTF-8 支援
表控制
數學函式
輸入輸出
作業系統庫
除錯庫

基礎函式

(只列出一些個人認為對初學者常用的)

assert (v [, message])
如果其引數 v 的值為假(nil 或 false), 它就呼叫 error; 否則,返回所有的引數。 在錯誤情況時, message 指那個錯誤物件; 如果不提供這個引數,引數預設為 “assertion failed!” 。

dofile ([filename])
開啟該名字的檔案,並執行檔案中的 Lua 程式碼塊。

error (message [, level])
中止上一次保護函式呼叫, 將錯誤物件 message 返回。level 引數指明瞭怎樣獲得出錯位置。 對於 level 1 (預設值),出錯位置指 error 函式呼叫的位置。 Level 2 將出錯位置指向呼叫 error的函式的函式;以此類推。 傳入 level 0 可以避免在訊息前新增出錯位置資訊。

_G
一個全域性變數(非函式), 內部儲存有全域性環境。 Lua 自己不使用這個變數; 改變這個變數的值不會對任何環境造成影響,反之亦然。

_VERSION
一個包含有當前直譯器版本號的全域性變數(並非函式)。 當前這個變數的值為 “Lua 5.3″。

getmetatable (object)
如果 object 不包含元表,返回 nil 。 否則,如果在該物件的元表中有 “__metatable” 域時返回其關聯值, 沒有時返回該物件的元表。

ipairs (t)
以下程式碼for i,v in ipairs(t) do body end
將迭代鍵值對(1,t[1]) ,(2,t[2]), … ,直到第一個空值。

pairs (t)
for k,v in pairs(t) do body end
能迭代表 t 中的所有鍵值對。

load (chunk [, chunkname [, mode [, env]]])
載入一個程式碼塊。
如果 chunk 是一個字串,程式碼塊指這個字串。 如果 chunk 是一個函式, load 不斷地呼叫它獲取程式碼塊的片斷。 每次對 chunk 的呼叫都必須返回一個字串緊緊連線在上次呼叫的返回串之後。 當返回空串、nil、或是不返回值時,都表示程式碼塊結束。
如果沒有語法錯誤, 則以函式形式返回編譯好的程式碼塊; 否則,返回 nil 加上錯誤訊息。
如果結果函式有上值, env 被設為第一個上值。 若不提供此引數,將全域性環境替代它。
chunkname 在錯誤訊息和除錯訊息中,用於程式碼塊的名字。 如果不提供此引數,它預設為字串chunk 。
字串 mode 用於控制程式碼塊是文字還是二進位制(即預編譯程式碼塊)。 它可以是字串 “b” (只能是二進位制程式碼塊), “t” (只能是文字程式碼塊), 或 “bt” (可以是二進位制也可以是文字)。 預設值為 “bt”。

loadfile ([filename [, mode [, env]]])
和 load 類似, 不過是從檔案 filename 或標準輸入(如果檔名未提供)中獲取程式碼塊。

next (table [, index])
執行程式來遍歷表中的所有域。 第一個引數是要遍歷的表,第二個引數是表中的某個鍵。 next 返回該鍵的下一個鍵及其關聯的值。 特別指出,你可以用 next(t) 來判斷一張表是否是空的。

pcall (f [, arg1, ···])
傳入引數,以 保護模式 呼叫函式 f 。 這意味著 f 中的任何錯誤不會丟擲; 取而代之的是,pcall 會將錯誤捕獲到,並返回一個狀態碼。 第一個返回值是狀態碼(一個布林量), 當沒有錯誤時,其為真。 此時,pcall 同樣會在狀態碼後返回所有呼叫的結果。 在有錯誤時,pcall 返回 false 加錯誤訊息。

xpcall (f, msgh [, arg1, ···])
這個函式和 pcall 類似。 不過它可以額外設定一個訊息處理器 msgh。

print (···)
接收任意數量的引數,並將它們的值列印到 stdout。 它用 tostring 函式將每個引數都轉換為字串。 print 不用於做格式化輸出。完整的對輸出的控制,請使用 string.format 以及 io.write

tostring (v)
可以接收任何型別,它將其轉換為人可閱讀的字串形式。

select (index, ···)
如果 index 是個數字, 那麼返回引數中第 index 個之後的部分; 負的數字會從後向前索引(-1 指最後一個引數)。 否則,index 必須是字串 “#”, 此時 select 返回引數的個數。

tonumber (e [, base])
如果呼叫的時候沒有 base, tonumber 嘗試把引數轉換為一個數字。

type (v)
型別判斷, 函式可能的返回值有 “nil” (一個字串,而不是 nil 值), “number”, “string”, “boolean”, “table”, “function”, “thread”, “userdata”。

協程管理

關於協程的操作作為基礎庫的一個子庫, 被放在一個獨立表 coroutine 中。

coroutine.create (f)
建立一個主體函式為 f 的新協程。 f 必須是一個 Lua 的函式。 返回這個新協程,它是一個型別為 “thread” 的物件。

coroutine.isyieldable ()
如果正在執行的協程可以讓出,則返回真。
不在主執行緒中或不在一個無法讓出的 C 函式中時,當前協程是可讓出的。

coroutine.resume (co [, val1, ···])
開始或繼續協程 co 的執行。 當你第一次延續一個協程,它會從主體函式處開始執行。 val1, … 這些值會以引數形式傳入主體函式。 如果該協程被讓出,resume 會重新啟動它; val1, … 這些引數會作為讓出點的返回值。

如果協程執行起來沒有錯誤, resume 返回 true 加上傳給 yield 的所有值 (當協程讓出), 或是主體函式的所有返回值(當協程中止)。 如果有任何錯誤發生, resume 返回 false 加錯誤訊息。

coroutine.running ()
返回當前正在執行的協程加一個布林量。 如果當前執行的協程是主執行緒,其為真。

coroutine.status (co)
以字串形式返回協程 co 的狀態: 當協程正在執行(它就是呼叫 status 的那個) ,返回 “running”; 如果協程呼叫 yield 掛起或是還沒有開始執行,返回 “suspended”; 如果協程是活動的,都並不在執行(即它正在延續其它協程),返回 “normal”; 如果協程執行完主體函式或因錯誤停止,返回 “dead”。

coroutine.wrap (f)
建立一個主體函式為 f 的新協程。 f 必須是一個 Lua 的函式。 返回一個函式, 每次呼叫該函式都會延續該協程。 傳給這個函式的引數都會作為 resume 的額外引數。 和 resume 返回相同的值, 只是沒有第一個布林量。 如果發生任何錯誤,丟擲這個錯誤。

coroutine.yield (···)
掛起正在呼叫的協程的執行。 傳遞給 yield 的引數都會轉為 resume 的額外返回值。

模組

包管理庫提供了從 Lua 中載入模組的基礎庫。 只有一個匯出函式直接放在全域性環境中: require。 所有其它的部分都匯出在表 package 中。

require (modname)
載入一個模組。 這個函式首先查詢 package.loaded 表, 檢測 modname 是否被載入過。 如果被載入過,require 返回 package.loaded[modname] 中儲存的值。 否則,它試著為模組尋找 載入器 。(require 遵循 package.searchers 序列的指引來查詢載入器。)

package.path
這個路徑被 require 在 Lua 載入器中做搜尋時用到。
在啟動時,Lua 用環境變數 LUA_PATH_5_3 或環境變數 LUA_PATH 來初始化這個變數。

package.searchers
用於 require 控制如何載入模組的表。

package.searchpath (name, path [, sep [, rep]])
在指定 path 中搜尋指定的 name 。

其餘,請看文件。

字串處理

這個庫提供了字串處理的通用函式。 例如字串查詢、子串、模式匹配等。 當在 Lua 中對字串做索引時,第一個字元從 1 開始計算(而不是 C 裡的 0 )。 索引可以是負數,它指從字串末尾反向解析。 即,最後一個字元在 -1 位置處,等等。
字串庫中的所有函式都在表 string 中。字串庫假定採用單位元組字元編碼。(這意味著不是原生支援中文。)

string.byte (s [, i [, j]])
返回字元 s[i], s[i+1], … ,s[j] 的內部數字編碼。

string.char (···)
接收零或更多的整數。 返回和引數數量相同長度的字串。

string.find (s, pattern [, init [, plain]])
查詢第一個字串 s 中匹配到的 pattern 。 如果找到一個匹配,find 會返回 s 中關於它起始及終點位置的索引; 否則,返回 nil。 第三個可選數字引數 init 指明從哪裡開始搜尋; 預設值為 1 ,同時可以是負值。 第四個可選引數 plain 為 true 時, 關閉模式匹配機制。 此時函式僅做直接的 “查詢子串”的操作.

string.format (formatstring, ···)
返回不定數量引數的格式化版本, 格式化串為第一個引數(必須是一個字串)。 格式化字串遵循 ISO C 函式 sprintf 的規則。

string.match (s, pattern [, init])
在字串 s 中找到第一個能用 pattern (參見 §6.4.1)匹配到的部分。 如果能找到,match 返回其中的捕獲物; 否則返回 nil 。 如果 pattern 中未指定捕獲, 返回整個 pattern 捕獲到的串。 第三個可選數字引數 init 指明從哪裡開始搜尋; 它預設為 1 且可以是負數。

string.gmatch (s, pattern)
返回一個迭代器函式。 每次呼叫這個函式都會繼續以 pattern (參見 §6.4.1) 對 s 做匹配,並返回所有捕獲到的值。 如果 pattern 中沒有指定捕獲,則每次捕獲整個 pattern。
下面這個例子會迴圈迭代字串 s 中所有的單詞, 並逐行列印:

 s = "hello world from Lua"
 for w in string.gmatch(s, "%a+") do
   print(w)
 end

下一個例子從指定的字串中收集所有的鍵值對 key=value 置入一張表:

 t = {}
 s = "from=world, to=Lua"
 for k, v in string.gmatch(s, "(%w+)=(%w+)") do
   t[k] = v
 end

對這個函式來說,模板前開始的 `^` 不會當成錨點。因為這樣會阻止迭代。

string.sub (s, i [, j])
返回 s 的子串, 該子串從 i 開始到 j 為止; i 和 j 都可以為負數。

string.gsub (s, pattern, repl [, n])
將字串 s 中,所有的(或是在 n 給出時的前 n 個) pattern (參見 §6.4.1)都替換成 repl ,並返回其副本。 repl 可以是字串、表、或函式。 gsub 還會在第二個返回值返回一共發生了多少次匹配。 這個和python中的re.sub有點類似。
如果 repl 是一個字串,那麼把這個字串作為替換品。 字元 % 是一個轉義符: repl 中的所有形式為 %d 的串表示 第 d 個捕獲到的子串,d 可以是 1 到 9 。 串 %0 表示整個匹配。 串 %% 表示單個 %。
如果 repl 是張表,每次匹配時都會用第一個捕獲物作為鍵去查這張表。
如果 repl 是個函式,則在每次匹配發生時都會呼叫這個函式。 所有捕獲到的子串依次作為引數傳入。
這裡有一些用例:

 x = string.gsub("hello world", "(%w+)", "%1 %1")
 --> x="hello hello world world"
 
 x = string.gsub("hello world", "%w+", "%0 %0", 1)
 --> x="hello hello world"
 
 x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")
 --> x="world hello Lua from"
 
 x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv)
 --> x="home = /home/roberto, user = roberto"
 
 x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)
       return load(s)()
     end)
 --> x="4+5 = 9"
 
 local t = {name="lua", version="5.3"}
 x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t)
 --> x="lua-5.3.tar.gz"
 

string.len (s)
接收一個字串,返回其長度。 空串 “” 的長度為 0 。

string.lower (s)
接收一個字串,將其中的大寫字元都轉為小寫後返回其副本。
string.upper (s)

string.pack (fmt, v1, v2, ···)
string.unpack (fmt, s [, pos])
返回一個打包了(即以二進位制形式序列化) v1, v2 等值的二進位制字串。 字串 fmt 為打包格式

string.rep (s, n [, sep])
返回 n 個字串 s 以字串 sep 為分割符連在一起的字串。 預設的 sep 值為空字串(即沒有分割符)。

string.reverse (s)
返回字串 s 的翻轉串。

匹配模式

Lua 中的匹配模式直接用常規的字串來描述。 它用於模式匹配函式 string.find, string.gmatch, string.gsub, string.match

字元類:
字元類 用於表示一個字符集合。 下列組合可用於字元類:

x: (這裡 x 不能是 魔法字元 ^$()%.[]*+-? 中的一員) 表示字元 x 自身。
.: (一個點)可表示任何字元。
%a: 表示任何字母。
%c: 表示任何控制字元。
%d: 表示任何數字。
%g: 表示任何除空白符外的可列印字元。
%l: 表示所有小寫字母。
%p: 表示所有標點符號。
%s: 表示所有空白字元。
%u: 表示所有大寫字母。
%w: 表示所有字母及數字。
%x: 表示所有 16 進位制數字符號。
%x: (這裡的 x 是任意非字母或數字的字元) 表示字元 x。 這是對魔法字元轉義的標準方法。 所有非字母或數字的字元 (包括所有標點,也包括非魔法字元) 都可以用前置一個 `%` 放在模式串中表示自身。

交叉使用類和範圍的行為未定義。 因此,像 [%a-z] 或 [a-%%] 這樣的模式串沒有意義。

所有單個字母表示的類別(%a,%c,等), 若將其字母改為大寫,均表示對應的補集。 例如,%S 表示所有非空格的字元。

如何定義字母、空格、或是其他字元組取決於當前的區域設定。 特別注意:[a-z] 未必等價於 %l 。

模式條目:
模式條目 可以是
單個字元類匹配該類別中任意單個字元;
單個字元類跟一個 `*`, 將匹配零或多個該類的字元。 這個條目總是匹配儘可能長的串;
單個字元類跟一個 `+`, 將匹配一或更多個該類的字元。 這個條目總是匹配儘可能長的串;
單個字元類跟一個 `-`, 將匹配零或更多個該類的字元。 和 `*` 不同, 這個條目總是匹配儘可能短的串;
單個字元類跟一個 `?`, 將匹配零或一個該類的字元。 只要有可能,它會匹配一個;
%n, 這裡的 n 可以從 1 到 9; 這個條目匹配一個等於 n 號捕獲物(後面有描述)的子串。
%bxy, 這裡的 x 和 y 是兩個明確的字元; 這個條目匹配以 x 開始 y 結束, 且其中 x 和 y 保持 平衡 的字串。 意思是,如果從左到右讀這個字串,對每次讀到一個 x 就 +1 ,讀到一個 y 就 -1, 最終結束處的那個 y 是第一個記數到 0 的 y。 舉個例子,條目 %b() 可以匹配到括號平衡的表示式。
%f[set], 指 邊境模式; 這個條目會匹配到一個位於 set 內某個字元之前的一個空串, 且這個位置的前一個字元不屬於 set 。 集合 set 的含義如前面所述。 匹配出的那個空串之開始和結束點的計算就看成該處有個字元 `0` 一樣。
模式:

模式 指一個模式條目的序列。 在模式最前面加上符號 `^` 將錨定從字串的開始處做匹配。 在模式最後面加上符號 `$` 將使匹配過程錨定到字串的結尾。 如果 `^` 和 `$` 出現在其它位置,它們均沒有特殊含義,只表示自身。

捕獲:
模式可以在內部用小括號括起一個子模式; 這些子模式被稱為 捕獲物。 當匹配成功時,由 捕獲物 匹配到的字串中的子串被儲存起來用於未來的用途。 捕獲物以它們左括號的次序來編號。 例如,對於模式 “(a(.)%w(%s))” , 字串中匹配到 “a(.)%w(%s)” 的部分儲存在第一個捕獲物中 (因此是編號 1 ); 由 “.” 匹配到的字元是 2 號捕獲物, 匹配到 “%s*” 的那部分是 3 號。

作為一個特例,空的捕獲 () 將捕獲到當前字串的位置(它是一個數字)。 例如,如果將模式 “()aa()” 作用到字串 “flaaap” 上,將產生兩個捕獲物: 3 和 5 。

UTF-8 支援

這個庫提供了對 UTF-8 編碼的基礎支援。 所有的函式都放在表 utf8 中。

utf8.char (···)
接收零或多個整數, 將每個整數轉換成對應的 UTF-8 位元組序列,並返回這些序列連線到一起的字串。

utf8.charpattern
用於精確匹配到一個 UTF-8 位元組序列的模式(是一個字串,並非函式)”0-x7FxC2-xF4*”

utf8.len (s [, i [, j]])
返回字串 s 中 從位置 i 到 j 間 (包括兩端) UTF-8 字元的個數。 預設的 i 為 1 ,預設的 j 為 -1 。

utf8.offset (s, n [, i])
返回編碼在 s 中的第 n 個字元的開始位置(按位元組數) (從位置 i 處開始統計)。

其餘看文件

表處理

這個庫提供了表處理的通用函式。 所有函式都放在表 table 中。

table.concat (list [, sep [, i [, j]]])
返回字串 list[i]..sep..list[i+1] ··· sep..list[j]。 sep 的預設值是空串, i 的預設值是 1 , j 的預設值是 #list 。 如果 i 比 j 大,返回空串。

table.insert (list, [pos,] value)
在 list 的位置 pos 處插入元素 value , 並後移元素 list[pos], list[pos+1], ···, list[#list] 。 pos 的預設值為 #list+1 , 因此呼叫 table.insert(t,x) 會將 x 插在列表 t 的末尾。

table.remove (list [, pos])
移除 list 中 pos 位置上的元素,並返回這個被移除的值。

table.sort (list [, comp])
在表內從 list[1] 到 list[#list] 原地 對其間元素按指定次序排序。 如果提供了 comp , 它必須是一個可以接收兩個列表內元素為引數的函式。 當第一個元素需要排在第二個元素之前時,返回真 (因此 not comp(list[i+1],list[i]) 在排序結束後將為真)。

table.pack (···)
返回用所有引數以鍵 1,2, 等填充的新表, 並將 “n” 這個域設為引數的總數。 注意這張返回的表不一定是一個序列。

table.unpack (list [, i [, j]])
返回列表中的元素。 這個函式等價於
return list[i], list[i+1], ···, list[j]
i 預設為 1 ,j 預設為 #list。

數學函式

這個庫提供了基本的數學函式。 所以函式都放在表 math 中。
略。。。

輸入輸出庫

I/O 庫提供了兩套不同風格的檔案處理介面。 第一種風格使用隱式的檔案控制程式碼; 它提供設定預設輸入檔案及預設輸出檔案的操作, 所有的輸入輸出操作都針對這些預設檔案。 第二種風格使用顯式的檔案控制程式碼。

當使用隱式檔案控制程式碼時, 所有的操作都由表 io 提供。 若使用顯式檔案控制程式碼, io.open 會返回一個檔案控制程式碼,且所有的操作都由該檔案控制程式碼的方法來提供。

表 io 中也提供了三個 和 C 中含義相同的預定義檔案控制程式碼: io.stdin, io.stdout, 以及 io.stderr。 I/O 庫永遠不會關閉這些檔案。

I/O 函式在出錯時都返回 nil (第二個返回值為錯誤訊息,第三個返回值為系統相關的錯誤碼)。 成功時返回與 nil 不同的值。

隱式檔案控制程式碼操作

io.close ([file])
等價於 file:close()。 不給出 file 時將關閉預設輸出檔案。

io.flush ()

io.lines ([filename ···])
讀模式開啟指定的檔名並返回一個迭代函式。 此迭代函式的工作方式和用一個已開啟的檔案去呼叫 file:lines(···) 得到的迭代器相同。 當迭代函式檢測到檔案結束, 它不返回值(讓迴圈結束)並自動關閉檔案
呼叫 io.lines() (不傳檔名) 等價於 io.input():lines(“*l”); 即,它將按行迭代標準輸入檔案。 在此情況下,迴圈結束後它不會關閉檔案。

io.open (filename [, mode])
這個函式用字串 mode 指定的模式開啟一個檔案。 返回新的檔案控制程式碼。 當出錯時,返回 nil 加錯誤訊息。
mode 字串可以是下列任意值:
“r”: 讀模式(預設);
“w”: 寫模式;
“a”: 追加模式;
“r+”: 更新模式,所有之前的資料都保留;
“w+”: 更新模式,所有之前的資料都刪除;
“a+”: 追加更新模式,所有之前的資料都保留,只允許在檔案尾部做寫入。
mode 字串可以在最後加一個 `b` , 這會在某些系統上以二進位制方式開啟檔案。

io.popen (prog [, mode])
這個函式和系統有關,不是所有的平臺都提供。
用一個分離程式開啟程式 prog, 返回的檔案控制程式碼可用於從這個程式中讀取資料 (如果 mode 為 “r”,這是預設值) 或是向這個程式寫入輸入(當 mode 為 “w” 時)。

io.input ([file])
用檔名呼叫它時,(以文字模式)來開啟該名字的檔案, 並將檔案控制程式碼設為預設輸入檔案。 如果用檔案控制程式碼去呼叫它, 就簡單的將該控制程式碼設為預設輸入檔案。 如果呼叫時不傳引數,它返回當前的預設輸入檔案。

io.read (···)
等價於 io.input():read(···)。

io.tmpfile ()
返回一個臨時檔案的控制程式碼。 這個檔案以更新模式開啟,在程式結束時會自動刪除。

io.type (obj)
檢查 obj 是否是合法的檔案控制程式碼。 如果 obj 它是一個開啟的檔案控制程式碼,返回字串 “file”。 如果 obj 是一個關閉的檔案控制程式碼,返回字串 “closed file”。 如果 obj 不是檔案控制程式碼,返回 nil 。

io.output ([file])
類似於 io.input。 不過都針對預設輸出檔案操作。

io.write (···)
等價於 io.output():write(···)。

顯式檔案控制程式碼操作
若使用顯式檔案控制程式碼, io.open 會返回一個檔案控制程式碼

file:close ()
關閉 file。

file:flush ()
將寫入的資料儲存到 file 中。

file:lines (···)
返回一個迭代器函式, 每次呼叫迭代器時,都從檔案中按指定格式讀資料。 如果沒有指定格式,使用預設值 “l” 。 看一個例子

for c in file:lines(1) do body end

會從檔案當前位置開始,中不斷讀出字元。 和 io.lines 不同, 這個函式在迴圈結束後不會關閉檔案。

file:read (···)
讀檔案 file, 指定的格式決定了要讀什麼。 對於每種格式,函式返回讀出的字元對應的字串或數字。 若不能以該格式對應讀出資料則返回 nil。 (對於最後這種情況, 函式不會讀出後續的格式。) 當呼叫時不傳格式,它會使用預設格式讀下一行(見下面描述)。
提供的格式有
“n”: 讀取一個數字,根據 Lua 的轉換文法,可能返回浮點數或整數。 (數字可以有前置或後置的空格,以及符號。) 只要能構成合法的數字,這個格式總是去讀儘量長的串; 如果讀出來的字首無法構成合法的數字 (比如空串,”0x” 或 “3.4e-“), 就中止函式執行,返回 nil。
“i”: 讀取一個整數,返回整數值。
“a”: 從當前位置開始讀取整個檔案。 如果已在檔案末尾,返回空串。
“l”: 讀取一行並忽略行結束標記。 當在檔案末尾時,返回 nil 這是預設格式。
“L”: 讀取一行並保留行結束標記(如果有的話), 當在檔案末尾時,返回 nil。
number: 讀取一個不超過這個數量位元組數的字串。 當在檔案末尾時,返回 nil。 如果 number 為零, 它什麼也不讀,返回一個空串。 當在檔案末尾時,返回 nil。
格式 “l” 和 “L” 只能用於文字檔案。

file:seek ([whence [, offset]])
設定及獲取基於檔案開頭處計算出的位置。 設定的位置由 offset 和 whence 字串 whence 指定的基點決定。基點可以是:
“set”: 基點為 0 (檔案開頭);
“cur”: 基點為當前位置了;
“end”: 基點為檔案尾;
當 seek 成功時,返回最終從檔案開頭計算起的檔案的位置。 當 seek 失敗時,返回 nil 加上一個錯誤描述字串。
whence 的預設值是 “cur”, offset 預設為 0 。 因此,呼叫 file:seek() 可以返回檔案當前位置,並不改變它; 呼叫 file:seek(“set”) 將位置設為檔案開頭(並返回 0); 呼叫 file:seek(“end”) 將位置設到檔案末尾,並返回檔案大小。

file:setvbuf (mode [, size])
設定輸出檔案的緩衝模式。 有三種模式:
“no”: 不緩衝;輸出操作立刻生效。
“full”: 完全緩衝;只有在快取滿或當你顯式的對檔案呼叫 flush(參見 io.flush) 時才真正做輸出操作。
“line”: 行緩衝; 輸出將到每次換行前, 對於某些特殊檔案(例如終端裝置)緩衝到任何輸入前。
對於後兩種情況,size 以位元組數為單位 指定緩衝區大小。 預設會有一個恰當的大小。

file:write (···)
將引數的值逐個寫入 file。 引數必須是字串或數字。
成功時,函式返回 file。 否則返回 nil 加錯誤描述字串。

作業系統庫

這個庫都通過表 os 實現。

os.clock ()
返回程式使用的按秒計 CPU 時間的近似值。

os.date ([format [, time]])
返回一個包含日期及時刻的字串或表。 格式化方法取決於所給字串 format。
如果提供了 time 引數, 格式化這個時間 (這個值的含義參見 os.time 函式)。 否則,date 格式化當前時間。
如果 format 以 `!` 打頭, 日期以協調世界時格式化。 在這個可選字元項之後, 如果 format 為字串 “*t”, date 返回有後續域的表: year (四位數字),month (1–12),day (1–31), hour (0–23),min (0–59),sec (0–61), wday (星期幾,星期天為 1 ), yday (當年的第幾天), 以及 isdst (夏令時標記,一個布林量)。 對於最後一個域,如果該資訊不提供的話就不存在。
如果 format 並非 “*t”, date 以字串形式返回, 格式化方法遵循 ISO C 函式 strftime 的規則。

os.difftime (t2, t1)
返回以秒計算的時刻 t1 到 t2 的差值。 (這裡的時刻是由 os.time 返回的值)。

os.execute ([command])
它呼叫系統直譯器執行 command。 如果命令成功執行完畢,第一個返回值就是 true, 否則是 nil。 在第一個返回值之後,函式返回一個字串加一個數字。如下:
“exit”: 命令正常結束; 接下來的數字是命令的退出狀態碼。
“signal”: 命令被訊號打斷; 接下來的數字是打斷該命令的訊號。

os.exit ([code [, close]])
呼叫 ISO C 函式 exit 終止宿主程式。 如果 code 為 true, 返回的狀態碼是 EXIT_SUCCESS; 如果 code 為 false, 返回的狀態碼是 EXIT_FAILURE; 如果 code 是一個數字, 返回的狀態碼就是這個數字。 code 的預設值為 true。

os.getenv (varname)
返回程式環境變數 varname 的值, 如果該變數未定義,返回 nil 。

os.remove (filename)
刪除指定名字的檔案(在 POSIX 系統上可以是一個空目錄) 如果函式失敗,返回 nil 加一個錯誤描述串及出錯碼。

os.rename (oldname, newname)
將名字為 oldname 的檔案或目錄更名為 newname。 如果函式失敗,返回 nil 加一個錯誤描述串及出錯碼。

os.time ([table])
當不傳引數時,返回當前時刻。 如果傳入一張表,就返回由這張表表示的時刻。 這張表必須包含域 year,month,及 day; 可以包含有 hour (預設為 12 ), min (預設為 0), sec (預設為 0),以及 isdst (預設為 nil)。

除錯庫

這個庫裡的所有函式都提供在表 debug 內。 所有操作執行緒的函式,可選的第一個引數都是針對的執行緒。 預設值永遠是當前執行緒。

debug.traceback ([thread,] [message [, level]])
如果 message 有,且不是字串或 nil, 函式不做任何處理直接返回 message。 否則,它返回撥用棧的棧回溯資訊。 字串可選項 message 被新增在棧回溯資訊的開頭。 數字可選項 level 指明從棧的哪一層開始回溯 (預設為 1 ,即呼叫 traceback 的那裡)。
其他,請看文件

獨立版 Lua

雖然 Lua 被設計成一門擴充套件式語言,用於嵌入一個宿主程式。 但經常也會被當成獨立語言使用。 獨立版的 Lua 語言直譯器隨標準包釋出,就叫 lua。 其命令列用法為:

lua [options] [script [args]]

選項有:

-e stat: 執行一段字串 stat ;
-l mod: “請求模組” mod ;
-i: 在執行完 指令碼 後進入互動模式;
-v: 列印版本資訊;
-E: 忽略環境變數;
--: 中止對後面選項的處理;
-: 把 stdin 當作一個檔案執行,並中止對後面選項的處理。

在處理完選項後,lua 執行指定的 指令碼。 如果不帶引數呼叫, 在標準輸入(stdin)是終端時,lua 的行為和 lua -v -i 相同。 否則相當於 lua – 。

為了讓 Lua 可以用於 Unix 系統的指令碼直譯器。

!/usr/local/bin/lua

如果 lua 在你的 PATH 中, 寫成 #!/usr/bin/env lua更為通用。

與之前版本(5.2)不相容的地方

該版本主要實現了對整數、位操作、UTF-8 的支援以及打包和解包的功能。
Lua 5.2 到 Lua 5.3 最大的變化是引入了數字的整數子型別,你可以通過把數字都強制轉換為浮點數來消除差異 (在 Lua 5.2 中,所有的數字都是浮點數)。
bit32 庫廢棄了。 使用一個外部相容庫很容易, 不過最好直接用對應的位操作符來替換它。 (注意 bit32 只能針對 32 位整數運算, 而標準 Lua 中的位操作可以用於 64 位整數。)
io.read 的選項名不再用 `*` 打頭。 但出於相容性考慮,Lua 會繼續忽略掉這個字元。
數學庫中的這些函式廢棄了: atan2, cosh, sinh, tanh, pow, frexp, 以及 ldexp 。 你可以用 x^y 替換 math.pow(x,y);
require 在搜尋 C 載入器時處理版本號的方式有所變化。 現在,版本號應該跟在模組名後(其它大多數工具都是這樣乾的)。 出於相容性考慮,如果使用新格式找不到載入器的話,搜尋器依然會嘗試舊格式。
可以參考:http://blog.codingnow.com/201…
http://blog.csdn.net/weiyuefe…

5.2與5.1的變化

5.1 與 5.2 是完全不相容的,相關的第三方庫必須重新為 5.2 適配。
luajit不支援5.2,5.3
具體見
http://www.lua.org/manual/5.2…