摘要:對于正常結(jié)束,將返回,并接上協(xié)程主函數(shù)的返回值。當(dāng)錯(cuò)誤發(fā)生時(shí),將返回與錯(cuò)誤消息。通過調(diào)用使協(xié)程暫停執(zhí)行,讓出執(zhí)行權(quán)。通用形式的通過一個(gè)叫作迭代器的函數(shù)工作。
Lua 是一門強(qiáng)大、輕量的嵌入式腳本語言,可供任何需要的程序使用。Lua 沒有 "main" 程序的概念: 它只能 嵌入 一個(gè)宿主程序中工作.宿主程序可以調(diào)用函數(shù)執(zhí)行一小段 Lua 代碼,可以讀寫 Lua 變量,可以注冊 C 函數(shù)讓 Lua 代碼調(diào)用。
Lua 是一門動(dòng)態(tài)類型語言。 這意味著變量沒有類型;只有值才有類型。
Lua 中所有的值都是 一等公民。 這意味著所有的值均可保存在變量中、 當(dāng)作參數(shù)傳遞給其它函數(shù)、以及作為返回值。
文檔: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 兩個(gè)值的類型。與其他語言不通的是nil 和 false 都會(huì)導(dǎo)致條件判斷為假; 而其它任何值都表示為真。而其它語言判斷比如0時(shí)為假,但lua為真。
Number 代表了整數(shù)和實(shí)數(shù)(浮點(diǎn)數(shù))。 它也按需作自動(dòng)轉(zhuǎn)換
String 表示一個(gè)不可變的字節(jié)序列。Lua 的字符串與編碼無關(guān); 它不關(guān)心字符串中具體內(nèi)容。
Lua 可以調(diào)用(以及操作)用 Lua 或 C 編寫的函數(shù)。 這兩種函數(shù)有統(tǒng)一類型 function。
userdata 類型允許將 C 中的數(shù)據(jù)保存在 Lua 變量中。 用戶數(shù)據(jù)類型的值是一個(gè)內(nèi)存塊, 有兩種用戶數(shù)據(jù): 完全用戶數(shù)據(jù) ,指一塊由 Lua 管理的內(nèi)存對應(yīng)的對象; 輕量用戶數(shù)據(jù) ,則指一個(gè)簡單的 C 指針。 用戶數(shù)據(jù)在 Lua 中除了賦值與相等性判斷之外沒有其他預(yù)定義的操作。 通過使用 元表 ,程序員可以給完全用戶數(shù)據(jù)定義一系列的操作。 你只能通過 C API 而無法在 Lua 代碼中創(chuàng)建或者修改用戶數(shù)據(jù)的值, 這保證了數(shù)據(jù)僅被宿主程序所控制。
thread 類型表示了一個(gè)獨(dú)立的執(zhí)行序列,被用于實(shí)現(xiàn)協(xié)程 。 Lua 的線程與操作系統(tǒng)的線程毫無關(guān)系。 Lua 為所有的系統(tǒng),包括那些不支持原生線程的系統(tǒng),提供了協(xié)程支持。
table 是一個(gè)關(guān)聯(lián)數(shù)組, 也就是說,這個(gè)數(shù)組不僅僅以數(shù)字做索引,除了 nil 和 NaN 之外的所有 Lua 值 都可以做索引。(Not a Number 是一個(gè)特殊的數(shù)字,它用于表示未定義或表示不了的運(yùn)算結(jié)果,比如 0/0。) 表可以是 異構(gòu) 的; 也就是說,表內(nèi)可以包含任何類型的值( nil 除外)。
表是 Lua 中唯一的數(shù)據(jù)結(jié)構(gòu), 它可被用于表示普通數(shù)組、序列、符號(hào)表、集合、記錄、圖、樹等等。 對于記錄,Lua 使用域名作為索引。 語言提供了 a.name 這樣的語法糖來替代 a["name"]。
我們使用 序列 這個(gè)術(shù)語來表示一個(gè)用 {1..n} 的正整數(shù)集做索引的表.注意:lua中索引從1開始,而非0
和索引一樣,表中每個(gè)域的值也可以是任何類型。 需要特別指出的是:既然函數(shù)是一等公民,那么表的域也可以是函數(shù)。 這樣,表就可以攜帶 方法 了。
表、函數(shù)、線程、以及完全用戶數(shù)據(jù)在 Lua 中被稱為 對象: 變量并不真的 持有 它們的值,而僅保存了對這些對象的 引用。 賦值、參數(shù)傳遞、函數(shù)返回,都是針對引用而不是針對值的操作, 這些操作均不會(huì)做任何形式的隱式拷貝。
類型判斷庫函數(shù) type 用于以字符串形式返回給定值的類型。
錯(cuò)誤處理由于 Lua 是一門嵌入式擴(kuò)展語言,其所有行為均源于宿主程序中 C 代碼對某個(gè) Lua 庫函數(shù)的調(diào)用。 (多帶帶使用 Lua 時(shí),lua 程序就是宿主程序。) 所以,在編譯或運(yùn)行 Lua 代碼塊的過程中,無論何時(shí)發(fā)生錯(cuò)誤, 控制權(quán)都返回給宿主,由宿主負(fù)責(zé)采取恰當(dāng)?shù)拇胧ū热绱蛴″e(cuò)誤消息)。
可以在 Lua 代碼中調(diào)用 error 函數(shù)來顯式地拋出一個(gè)錯(cuò)誤。 如果你需要在 Lua 中捕獲這些錯(cuò)誤, 可以使用 pcall 或 xpcall 在 保護(hù)模式 下調(diào)用一個(gè)函數(shù)。
無論何時(shí)出現(xiàn)錯(cuò)誤,都會(huì)拋出一個(gè)攜帶錯(cuò)誤信息的 錯(cuò)誤對象 (錯(cuò)誤消息),這是一個(gè)字符串對象。
使用 xpcall 或 lua_pcall 時(shí), 你應(yīng)該提供一個(gè) 消息處理函數(shù) 用于錯(cuò)誤拋出時(shí)調(diào)用。 該函數(shù)需接收原始的錯(cuò)誤消息,并返回一個(gè)新的錯(cuò)誤消息。
Lua 中的每個(gè)值都可以有一個(gè) 元表。 這個(gè) 元表 就是一個(gè)普通的 Lua 表, 它用于定義原始值在特定操作下的行為。元表中的鍵對應(yīng)著不同的 事件 名; 鍵關(guān)聯(lián)的那些值被稱為 元方法。
你可以用 getmetatable 函數(shù) 來獲取任何值的元表。
使用 setmetatable 來替換一張表的元表。在 Lua 中,你不可以改變表以外其它類型的值的元表 (除非你使用調(diào)試庫); 若想改變這些非表類型的值的元表,請使用 C API。
表和完全用戶數(shù)據(jù)有獨(dú)立的元表 (當(dāng)然,多個(gè)表和用戶數(shù)據(jù)可以共享同一個(gè)元表)。 其它類型的值按類型共享元表; 也就是說所有的數(shù)字都共享同一個(gè)元表, 所有的字符串共享另一個(gè)元表等等。
元表決定了一個(gè)對象在數(shù)學(xué)運(yùn)算、位運(yùn)算、比較、連接、 取長度、調(diào)用、索引時(shí)的行為。 元表還可以定義一個(gè)函數(shù),當(dāng)表對象或用戶數(shù)據(jù)對象在垃圾回收時(shí)調(diào)用它。
其它具體見文檔。。。。
Lua 采用了自動(dòng)內(nèi)存管理。Lua 實(shí)現(xiàn)了一個(gè)增量標(biāo)記-掃描收集器。
垃圾收集元方法:
你可以為表設(shè)定垃圾收集的元方法,對于完全用戶數(shù)據(jù), 則需要使用 C API 。 該元方法被稱為 終結(jié)器。 終結(jié)器允許你配合 Lua 的垃圾收集器做一些額外的資源管理工作 (例如關(guān)閉文件、網(wǎng)絡(luò)或數(shù)據(jù)庫連接,或是釋放一些你自己的內(nèi)存)。
如果要讓一個(gè)對象(表或用戶數(shù)據(jù))在收集過程中進(jìn)入終結(jié)流程, 你必須 標(biāo)記 它需要觸發(fā)終結(jié)器。 當(dāng)你為一個(gè)對象設(shè)置元表時(shí),若此刻這張?jiān)碇杏靡粋€(gè)以字符串 "__gc" 為索引的域,那么就標(biāo)記了這個(gè)對象需要觸發(fā)終結(jié)器。
調(diào)用函數(shù) coroutine.create 可創(chuàng)建一個(gè)協(xié)程。 其唯一的參數(shù)是該協(xié)程的主函數(shù)。 create 函數(shù)只負(fù)責(zé)新建一個(gè)協(xié)程并返回其句柄 (一個(gè) thread 類型的對象); 而不會(huì)啟動(dòng)該協(xié)程。
調(diào)用 coroutine.resume 函數(shù)執(zhí)行一個(gè)協(xié)程。
協(xié)程的運(yùn)行可能被兩種方式終止: 正常途徑是主函數(shù)返回 (顯式返回或運(yùn)行完最后一條指令); 非正常途徑是發(fā)生了一個(gè)未被捕獲的錯(cuò)誤。 對于正常結(jié)束, coroutine.resume 將返回 true, 并接上協(xié)程主函數(shù)的返回值。 當(dāng)錯(cuò)誤發(fā)生時(shí), coroutine.resume 將返回 false 與錯(cuò)誤消息。
通過調(diào)用 coroutine.yield 使協(xié)程暫停執(zhí)行,讓出執(zhí)行權(quán)。 協(xié)程讓出時(shí),對應(yīng)的最近 coroutine.resume 函數(shù)會(huì)立刻返回,即使該讓出操作發(fā)生在內(nèi)嵌函數(shù)調(diào)用中 (即不在主函數(shù),但在主函數(shù)直接或間接調(diào)用的函數(shù)內(nèi)部)。 在協(xié)程讓出的情況下, coroutine.resume 也會(huì)返回 true, 并加上傳給 coroutine.yield 的參數(shù)。 當(dāng)下次重啟同一個(gè)協(xié)程時(shí), 協(xié)程會(huì)接著從讓出點(diǎn)繼續(xù)執(zhí)行。
與 coroutine.create 類似, coroutine.wrap 函數(shù)也會(huì)創(chuàng)建一個(gè)協(xié)程。 不同之處在于,它不返回協(xié)程本身,而是返回一個(gè)函數(shù)。 調(diào)用這個(gè)函數(shù)將啟動(dòng)該協(xié)程。 傳遞給該函數(shù)的任何參數(shù)均當(dāng)作 coroutine.resume 的額外參數(shù)。 coroutine.wrap 返回 coroutine.resume 的所有返回值,除了第一個(gè)返回值(布爾型的錯(cuò)誤碼)。 和 coroutine.resume 不同, coroutine.wrap 不會(huì)捕獲錯(cuò)誤; 而是將任何錯(cuò)誤都傳播給調(diào)用者。
下面的代碼展示了一個(gè)協(xié)程工作的范例:
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")) 當(dāng)你運(yùn)行它,將產(chǎn)生下列輸出: 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 來創(chuàng)建及操作協(xié)程: 參見函數(shù) lua_newthread, lua_resume, 以及 lua_yield。
語言定義Lua 語言的格式自由。 它會(huì)忽略語法元素(符記)間的空格(包括換行)和注釋, 僅把它們看作為名字和關(guān)鍵字間的分割符。
Lua 語言對大小寫敏感。
字面串 可以用單引號(hào)或雙引號(hào)括起。 字面串內(nèi)部可以包含下列 C 風(fēng)格的轉(zhuǎn)義串。
轉(zhuǎn)義串 "z" 會(huì)忽略其后的一系列空白符,包括換行; 它在你需要對一個(gè)很長的字符串常量斷行為多行并希望在每個(gè)新行保持縮進(jìn)時(shí)非常有用。
對于用 UTF-8 編碼的 Unicode 字符,你可以用 轉(zhuǎn)義符 u{XXX} 來表示
代碼注釋:
--這是行注釋 --[[這是塊 注釋]]變量:
Lua 中有三種變量: 全局變量、局部變量和表的域。
所有沒有顯式聲明為局部變量的變量名都被當(dāng)做全局變量。 這一點(diǎn)倒是和js很相似。
全局變量 x = 1234 的賦值等價(jià)于 _ENV.x = 1234
局部變量 local namelist [‘=’ explist] 比如 local name="xbynet"
每個(gè)語句結(jié)尾的分號(hào)(;)是可選的,但如果同一行有多個(gè)語句最好用;分開
-- 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在調(diào)試或者測試Lua代碼時(shí)是很方便的。
命令行方式
> lua -e "print(math.sin(12))" --> -0.53657291800043
全局變量arg存放Lua的命令行參數(shù)。
prompt> lua script a b c
在運(yùn)行以前,Lua使用所有參數(shù)構(gòu)造arg表。腳本名索引為0,腳本的參數(shù)從1開始增加。腳本前面的參數(shù)從-1開始減少。
if, while, and repeat 這些控制結(jié)構(gòu)符合通常的意義,而且也有類似的語法:
while exp do block end repeat block until exp if exp then block elseif exp then block else block end
for 有兩種形式:一種是數(shù)字形式,另一種是通用形式。
數(shù)值for循環(huán):
for var=exp1,exp2,exp3 do loop-part end
for將用exp3作為step從exp1(初始值)到exp2(終止值),執(zhí)行l(wèi)oop-part。其中exp3可以省略,默認(rèn)step=1
有幾點(diǎn)需要注意:
三個(gè)表達(dá)式只會(huì)被計(jì)算一次,并且是在循環(huán)開始前。
for i=1,f(x) do
print(i)
end
for i=10,1,-1 do
print(i)
end
第一個(gè)例子f(x)只會(huì)在循環(huán)前被調(diào)用一次。
通用形式的 for 通過一個(gè)叫作 迭代器 的函數(shù)工作。 每次迭代,迭代器函數(shù)都會(huì)被調(diào)用以產(chǎn)生一個(gè)新的值, 當(dāng)這個(gè)值為 nil 時(shí),循環(huán)停止。
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 再看一個(gè)遍歷表key的例子: -- print all keys of table "t" for k in pairs(t) do print(k) end
控制結(jié)構(gòu)中的條件表達(dá)式可以返回任何值。 false 與 nil 兩者都被認(rèn)為是假。 所有不同于 nil 與 false 的其它值都被認(rèn)為是真 (特別需要注意的是,數(shù)字 0 和空字符串也被認(rèn)為是真)。
有break,但是沒有continue
return 被用于從函數(shù)或是代碼塊(其實(shí)它就是一個(gè)函數(shù)) 中返回值。 函數(shù)可以返回不止一個(gè)值。
return 只能被寫在一個(gè)語句塊的最后一句。 如果你真的需要從語句塊的中間 return, 你可以使用顯式的定義一個(gè)內(nèi)部語句塊, 一般寫作 do return end。 可以這樣寫是因?yàn)楝F(xiàn)在 return 成了(內(nèi)部)語句塊的最后一句了。
Lua語法要求break和return只能出現(xiàn)在block的結(jié)尾一句(也就是說:作為chunk的最后一句,或者在end之前,或者else前,或者until前),例如:
local i = 1 while a[i] do if a[i] == v then break end i = i + 1 end
有時(shí)候?yàn)榱苏{(diào)試或者其他目的需要在block的中間使用return或者break,可以顯式的使用do..end來實(shí)現(xiàn):
function foo () return --<< SYNTAX ERROR -- "return" is the last statement in the next block do return end -- OK ... -- statements not reached end表達(dá)式
數(shù)學(xué)運(yùn)算操作符
+: 加法 -: 減法 *: 乘法 /: 浮點(diǎn)除法 //: 向下取整除法 %: 取模 ^: 乘方 -: 取負(fù)
比較操作符
==: 等于 ~=: 不等于 <: 小于 >: 大于 <=: 小于等于 >=: 大于等于
注意:不等于是~=,而不是!=
這些操作的結(jié)果不是 false 就是 true。
等于操作 (==)先比較操作數(shù)的類型。 如果類型不同,結(jié)果就是 false。 否則,繼續(xù)比較值。 字符串按一般的方式比較。 數(shù)字遵循二元操作的規(guī)則
表,用戶數(shù)據(jù),以及線程都按引用比較: 只有兩者引用同一個(gè)對象時(shí)才認(rèn)為它們相等。
你可以通過使用 "eq" 元方法來改變 Lua 比較表和用戶數(shù)據(jù)時(shí)的方式。
邏輯操作符
Lua 中的邏輯操作符有 and, or,以及 not。
和控制結(jié)構(gòu)一樣, 所有的邏輯操作符把 false 和 nil 都作為假, 而其它的一切都當(dāng)作真。
字符串連接
Lua 中字符串的連接操作符寫作兩個(gè)點(diǎn)("..")。 如果兩個(gè)操作數(shù)都是字符串或都是數(shù)字, 連接操作將以中提到的規(guī)則把其轉(zhuǎn)換為字符串。 否則,會(huì)調(diào)用元方法 __concat
多行字符串
還可以使用[[...]]表示字符串。這種形式的字符串可以包含多行
page = [[ qwwqwq adas ss ]]
取長度操作符
取長度操作符寫作一元前置符 #。 字符串的長度是它的字節(jié)數(shù)(就是以一個(gè)字符一個(gè)字節(jié)計(jì)算的字符串長度)。而Python是內(nèi)置的len()函數(shù),Java和JS都是字符串函數(shù).length()
程序可以通過 __len 元方法來修改對字符串類型外的任何值的取長度操作行為。
表構(gòu)造子是一個(gè)構(gòu)造表的表達(dá)式。 每次構(gòu)造子被執(zhí)行,都會(huì)構(gòu)造出一張新的表。 構(gòu)造子可以被用來構(gòu)造一張空表, 也可以用來構(gòu)造一張表并初始化其中的一些域。
構(gòu)造器是創(chuàng)建和初始化表的表達(dá)式。表是Lua特有的功能強(qiáng)大的東西。最簡單的構(gòu)造函數(shù)是{},用來創(chuàng)建一個(gè)空表。可以直接初始化數(shù)組:
days = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}
Lua將"Sunday"初始化days[1](第一個(gè)元素索引為1),用"Monday"初始化days[2]...
如果想初始化一個(gè)表作為record使用可以這樣:
a = {x=0, y=0} <--> a = {}; a.x=0; a.y=0
不管用何種方式創(chuàng)建table,我們都可以向表中添加或者刪除任何類型的域,構(gòu)造函數(shù)僅僅影響表的初始化。
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"
在構(gòu)造函數(shù)中域分隔符逗號(hào)(",")可以用分號(hào)(";")替代,通常我們使用分號(hào)用來分割不同類型的表元素。
{x=10, y=45; "one", "two", "three"}
舉個(gè)例子:
a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 }
等價(jià)于
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
如果表單中最后一個(gè)域的形式是 exp , 而且其表達(dá)式是一個(gè)函數(shù)調(diào)用或者是一個(gè)可變參數(shù), 那么這個(gè)表達(dá)式所有的返回值將依次進(jìn)入列表
函數(shù)函數(shù)定義
function f () body end local function f () body end
當(dāng)一個(gè)函數(shù)被調(diào)用, 如果函數(shù)并非一個(gè) 可變參數(shù)函數(shù), 即在形參列表的末尾注明三個(gè)點(diǎn) ("..."), 那么實(shí)參列表就會(huì)被調(diào)整到形參列表的長度。
function f(a, b) end function g(a, b, ...) end function r() return 1,2,3 end
下面看看實(shí)參到形參數(shù)以及可變長參數(shù)的映射關(guān)系:
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
冒號(hào) 語法可以用來定義 方法, 就是說,函數(shù)可以有一個(gè)隱式的形參 self。 因此,如下語句
function t.a.b.c:f (params) body end
是這樣一種寫法的語法糖
t.a.b.c.f = function (self, params) body end
Lua函數(shù)可以返回多個(gè)結(jié)果值
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總是調(diào)整函數(shù)返回值的個(gè)數(shù)以適用調(diào)用環(huán)境,當(dāng)作為獨(dú)立的語句調(diào)用函數(shù)時(shí),所有返回值將被忽略
第一,當(dāng)作為表達(dá)式調(diào)用函數(shù)時(shí),有以下幾種情況:
當(dāng)調(diào)用作為表達(dá)式最后一個(gè)參數(shù)或者僅有一個(gè)參數(shù)時(shí),根據(jù)變量個(gè)數(shù)函數(shù)盡可能多地返回多個(gè)值,不足補(bǔ)nil,超出舍去。
其他情況下,函數(shù)調(diào)用僅返回第一個(gè)值(如果沒有返回值為nil)
第二,函數(shù)調(diào)用作為函數(shù)參數(shù)被調(diào)用時(shí),和多值賦值是相同。
第三,函數(shù)調(diào)用在表構(gòu)造函數(shù)中初始化時(shí),和多值賦值時(shí)相同。
可變參數(shù)與命名參數(shù)
printResult = "" function print(...) for i,v in ipairs(arg) do printResult = printResult .. tostring(v) .. " " end printResult = printResult .. " " end
命名參數(shù)用表來作為參數(shù)傳遞。
可見性規(guī)則Lua 語言有詞法作用范圍。 變量的作用范圍開始于聲明它們之后的第一個(gè)語句段, 結(jié)束于包含這個(gè)聲明的最內(nèi)層語句塊的最后一個(gè)非空語句。
x = 10 -- 全局變量 do -- 新的語句塊 local x = x -- 新的一個(gè) "x", 它的值現(xiàn)在是 10 print(x) --> 10 x = x+1 do -- 另一個(gè)語句塊 local x = x+1 -- 又一個(gè) "x" print(x) --> 12 end print(x) --> 11 end print(x) --> 10 (取到的是全局的那一個(gè))
局部變量可以被在它的作用范圍內(nèi)定義的函數(shù)自由使用。 當(dāng)一個(gè)局部變量被內(nèi)層的函數(shù)中使用的時(shí)候, 它被內(nèi)層函數(shù)稱作 上值,或是 外部局部變量。
注意,每次執(zhí)行到一個(gè) local 語句都會(huì)定義出一個(gè)新的局部變量。 看看這樣一個(gè)例子:
a = {} local x = 20 for i=1,10 do local y = 0 a[i] = function () y=y+1; return x+y end end
這個(gè)循環(huán)創(chuàng)建了十個(gè)閉包(這指十個(gè)匿名函數(shù)的實(shí)例)。 這些閉包中的每一個(gè)都使用了不同的 y 變量, 而它們又共享了同一份 x。
C API接口由于,目前關(guān)注重點(diǎn)在于簡單的redis與Lua及nginx與lua交互,故而暫時(shí)略去此部分學(xué)習(xí)。。。
標(biāo)準(zhǔn)庫所有的庫都是直接用 C API 實(shí)現(xiàn)的,并以分離的 C 模塊形式提供。 目前,Lua 有下列標(biāo)準(zhǔn)庫:
基礎(chǔ)庫
協(xié)程庫
包管理庫
字符串控制
基礎(chǔ) UTF-8 支持
表控制
數(shù)學(xué)函數(shù)
輸入輸出
操作系統(tǒng)庫
調(diào)試庫
(只列出一些個(gè)人認(rèn)為對初學(xué)者常用的)
assert (v [, message])
如果其參數(shù) v 的值為假(nil 或 false), 它就調(diào)用 error; 否則,返回所有的參數(shù)。 在錯(cuò)誤情況時(shí), message 指那個(gè)錯(cuò)誤對象; 如果不提供這個(gè)參數(shù),參數(shù)默認(rèn)為 "assertion failed!" 。
dofile ([filename])
打開該名字的文件,并執(zhí)行文件中的 Lua 代碼塊。
error (message [, level])
中止上一次保護(hù)函數(shù)調(diào)用, 將錯(cuò)誤對象 message 返回。level 參數(shù)指明了怎樣獲得出錯(cuò)位置。 對于 level 1 (默認(rèn)值),出錯(cuò)位置指 error 函數(shù)調(diào)用的位置。 Level 2 將出錯(cuò)位置指向調(diào)用 error的函數(shù)的函數(shù);以此類推。 傳入 level 0 可以避免在消息前添加出錯(cuò)位置信息。
_G
一個(gè)全局變量(非函數(shù)), 內(nèi)部儲(chǔ)存有全局環(huán)境。 Lua 自己不使用這個(gè)變量; 改變這個(gè)變量的值不會(huì)對任何環(huán)境造成影響,反之亦然。
_VERSION
一個(gè)包含有當(dāng)前解釋器版本號(hào)的全局變量(并非函數(shù))。 當(dāng)前這個(gè)變量的值為 "Lua 5.3"。
getmetatable (object)
如果 object 不包含元表,返回 nil 。 否則,如果在該對象的元表中有 "__metatable" 域時(shí)返回其關(guān)聯(lián)值, 沒有時(shí)返回該對象的元表。
ipairs (t)
以下代碼for i,v in ipairs(t) do body end
將迭代鍵值對(1,t[1]) ,(2,t[2]), ... ,直到第一個(gè)空值。
pairs (t)
for k,v in pairs(t) do body end
能迭代表 t 中的所有鍵值對。
load (chunk [, chunkname [, mode [, env]]])
加載一個(gè)代碼塊。
如果 chunk 是一個(gè)字符串,代碼塊指這個(gè)字符串。 如果 chunk 是一個(gè)函數(shù), load 不斷地調(diào)用它獲取代碼塊的片斷。 每次對 chunk 的調(diào)用都必須返回一個(gè)字符串緊緊連接在上次調(diào)用的返回串之后。 當(dāng)返回空串、nil、或是不返回值時(shí),都表示代碼塊結(jié)束。
如果沒有語法錯(cuò)誤, 則以函數(shù)形式返回編譯好的代碼塊; 否則,返回 nil 加上錯(cuò)誤消息。
如果結(jié)果函數(shù)有上值, env 被設(shè)為第一個(gè)上值。 若不提供此參數(shù),將全局環(huán)境替代它。
chunkname 在錯(cuò)誤消息和調(diào)試消息中,用于代碼塊的名字。 如果不提供此參數(shù),它默認(rèn)為字符串chunk 。
字符串 mode 用于控制代碼塊是文本還是二進(jìn)制(即預(yù)編譯代碼塊)。 它可以是字符串 "b" (只能是二進(jìn)制代碼塊), "t" (只能是文本代碼塊), 或 "bt" (可以是二進(jìn)制也可以是文本)。 默認(rèn)值為 "bt"。
loadfile ([filename [, mode [, env]]])
和 load 類似, 不過是從文件 filename 或標(biāo)準(zhǔn)輸入(如果文件名未提供)中獲取代碼塊。
next (table [, index])
運(yùn)行程序來遍歷表中的所有域。 第一個(gè)參數(shù)是要遍歷的表,第二個(gè)參數(shù)是表中的某個(gè)鍵。 next 返回該鍵的下一個(gè)鍵及其關(guān)聯(lián)的值。 特別指出,你可以用 next(t) 來判斷一張表是否是空的。
pcall (f [, arg1, ···])
傳入?yún)?shù),以 保護(hù)模式 調(diào)用函數(shù) f 。 這意味著 f 中的任何錯(cuò)誤不會(huì)拋出; 取而代之的是,pcall 會(huì)將錯(cuò)誤捕獲到,并返回一個(gè)狀態(tài)碼。 第一個(gè)返回值是狀態(tài)碼(一個(gè)布爾量), 當(dāng)沒有錯(cuò)誤時(shí),其為真。 此時(shí),pcall 同樣會(huì)在狀態(tài)碼后返回所有調(diào)用的結(jié)果。 在有錯(cuò)誤時(shí),pcall 返回 false 加錯(cuò)誤消息。
xpcall (f, msgh [, arg1, ···])
這個(gè)函數(shù)和 pcall 類似。 不過它可以額外設(shè)置一個(gè)消息處理器 msgh。
print (···)
接收任意數(shù)量的參數(shù),并將它們的值打印到 stdout。 它用 tostring 函數(shù)將每個(gè)參數(shù)都轉(zhuǎn)換為字符串。 print 不用于做格式化輸出。完整的對輸出的控制,請使用 string.format 以及 io.write。
tostring (v)
可以接收任何類型,它將其轉(zhuǎn)換為人可閱讀的字符串形式。
select (index, ···)
如果 index 是個(gè)數(shù)字, 那么返回參數(shù)中第 index 個(gè)之后的部分; 負(fù)的數(shù)字會(huì)從后向前索引(-1 指最后一個(gè)參數(shù))。 否則,index 必須是字符串 "#", 此時(shí) select 返回參數(shù)的個(gè)數(shù)。
tonumber (e [, base])
如果調(diào)用的時(shí)候沒有 base, tonumber 嘗試把參數(shù)轉(zhuǎn)換為一個(gè)數(shù)字。
type (v)
類型判斷, 函數(shù)可能的返回值有 "nil" (一個(gè)字符串,而不是 nil 值), "number", "string", "boolean", "table", "function", "thread", "userdata"。
關(guān)于協(xié)程的操作作為基礎(chǔ)庫的一個(gè)子庫, 被放在一個(gè)獨(dú)立表 coroutine 中。
coroutine.create (f)
創(chuàng)建一個(gè)主體函數(shù)為 f 的新協(xié)程。 f 必須是一個(gè) Lua 的函數(shù)。 返回這個(gè)新協(xié)程,它是一個(gè)類型為 "thread" 的對象。
coroutine.isyieldable ()
如果正在運(yùn)行的協(xié)程可以讓出,則返回真。
不在主線程中或不在一個(gè)無法讓出的 C 函數(shù)中時(shí),當(dāng)前協(xié)程是可讓出的。
coroutine.resume (co [, val1, ···])
開始或繼續(xù)協(xié)程 co 的運(yùn)行。 當(dāng)你第一次延續(xù)一個(gè)協(xié)程,它會(huì)從主體函數(shù)處開始運(yùn)行。 val1, ... 這些值會(huì)以參數(shù)形式傳入主體函數(shù)。 如果該協(xié)程被讓出,resume 會(huì)重新啟動(dòng)它; val1, ... 這些參數(shù)會(huì)作為讓出點(diǎn)的返回值。
如果協(xié)程運(yùn)行起來沒有錯(cuò)誤, resume 返回 true 加上傳給 yield 的所有值 (當(dāng)協(xié)程讓出), 或是主體函數(shù)的所有返回值(當(dāng)協(xié)程中止)。 如果有任何錯(cuò)誤發(fā)生, resume 返回 false 加錯(cuò)誤消息。
coroutine.running ()
返回當(dāng)前正在運(yùn)行的協(xié)程加一個(gè)布爾量。 如果當(dāng)前運(yùn)行的協(xié)程是主線程,其為真。
coroutine.status (co)
以字符串形式返回協(xié)程 co 的狀態(tài): 當(dāng)協(xié)程正在運(yùn)行(它就是調(diào)用 status 的那個(gè)) ,返回 "running"; 如果協(xié)程調(diào)用 yield 掛起或是還沒有開始運(yùn)行,返回 "suspended"; 如果協(xié)程是活動(dòng)的,都并不在運(yùn)行(即它正在延續(xù)其它協(xié)程),返回 "normal"; 如果協(xié)程運(yùn)行完主體函數(shù)或因錯(cuò)誤停止,返回 "dead"。
coroutine.wrap (f)
創(chuàng)建一個(gè)主體函數(shù)為 f 的新協(xié)程。 f 必須是一個(gè) Lua 的函數(shù)。 返回一個(gè)函數(shù), 每次調(diào)用該函數(shù)都會(huì)延續(xù)該協(xié)程。 傳給這個(gè)函數(shù)的參數(shù)都會(huì)作為 resume 的額外參數(shù)。 和 resume 返回相同的值, 只是沒有第一個(gè)布爾量。 如果發(fā)生任何錯(cuò)誤,拋出這個(gè)錯(cuò)誤。
coroutine.yield (···)
掛起正在調(diào)用的協(xié)程的執(zhí)行。 傳遞給 yield 的參數(shù)都會(huì)轉(zhuǎn)為 resume 的額外返回值。
包管理庫提供了從 Lua 中加載模塊的基礎(chǔ)庫。 只有一個(gè)導(dǎo)出函數(shù)直接放在全局環(huán)境中: require。 所有其它的部分都導(dǎo)出在表 package 中。
require (modname)
加載一個(gè)模塊。 這個(gè)函數(shù)首先查找 package.loaded 表, 檢測 modname 是否被加載過。 如果被加載過,require 返回 package.loaded[modname] 中保存的值。 否則,它試著為模塊尋找 加載器 。(require 遵循 package.searchers 序列的指引來查找加載器。)
package.path
這個(gè)路徑被 require 在 Lua 加載器中做搜索時(shí)用到。
在啟動(dòng)時(shí),Lua 用環(huán)境變量 LUA_PATH_5_3 或環(huán)境變量 LUA_PATH 來初始化這個(gè)變量。
package.searchers
用于 require 控制如何加載模塊的表。
package.searchpath (name, path [, sep [, rep]])
在指定 path 中搜索指定的 name 。
其余,請看文檔。
字符串處理這個(gè)庫提供了字符串處理的通用函數(shù)。 例如字符串查找、子串、模式匹配等。 當(dāng)在 Lua 中對字符串做索引時(shí),第一個(gè)字符從 1 開始計(jì)算(而不是 C 里的 0 )。 索引可以是負(fù)數(shù),它指從字符串末尾反向解析。 即,最后一個(gè)字符在 -1 位置處,等等。
字符串庫中的所有函數(shù)都在表 string 中。字符串庫假定采用單字節(jié)字符編碼。(這意味著不是原生支持中文。)
string.byte (s [, i [, j]])
返回字符 s[i], s[i+1], ... ,s[j] 的內(nèi)部數(shù)字編碼。
string.char (···)
接收零或更多的整數(shù)。 返回和參數(shù)數(shù)量相同長度的字符串。
string.find (s, pattern [, init [, plain]])
查找第一個(gè)字符串 s 中匹配到的 pattern 。 如果找到一個(gè)匹配,find 會(huì)返回 s 中關(guān)于它起始及終點(diǎn)位置的索引; 否則,返回 nil。 第三個(gè)可選數(shù)字參數(shù) init 指明從哪里開始搜索; 默認(rèn)值為 1 ,同時(shí)可以是負(fù)值。 第四個(gè)可選參數(shù) plain 為 true 時(shí), 關(guān)閉模式匹配機(jī)制。 此時(shí)函數(shù)僅做直接的 “查找子串”的操作.
string.format (formatstring, ···)
返回不定數(shù)量參數(shù)的格式化版本, 格式化串為第一個(gè)參數(shù)(必須是一個(gè)字符串)。 格式化字符串遵循 ISO C 函數(shù) sprintf 的規(guī)則。
string.match (s, pattern [, init])
在字符串 s 中找到第一個(gè)能用 pattern (參見 §6.4.1)匹配到的部分。 如果能找到,match 返回其中的捕獲物; 否則返回 nil 。 如果 pattern 中未指定捕獲, 返回整個(gè) pattern 捕獲到的串。 第三個(gè)可選數(shù)字參數(shù) init 指明從哪里開始搜索; 它默認(rèn)為 1 且可以是負(fù)數(shù)。
string.gmatch (s, pattern)
返回一個(gè)迭代器函數(shù)。 每次調(diào)用這個(gè)函數(shù)都會(huì)繼續(xù)以 pattern (參見 §6.4.1) 對 s 做匹配,并返回所有捕獲到的值。 如果 pattern 中沒有指定捕獲,則每次捕獲整個(gè) pattern。
下面這個(gè)例子會(huì)循環(huán)迭代字符串 s 中所有的單詞, 并逐行打印:
s = "hello world from Lua" for w in string.gmatch(s, "%a+") do print(w) end
下一個(gè)例子從指定的字符串中收集所有的鍵值對 key=value 置入一張表:
t = {} s = "from=world, to=Lua" for k, v in string.gmatch(s, "(%w+)=(%w+)") do t[k] = v end
對這個(gè)函數(shù)來說,模板前開始的 "^" 不會(huì)當(dāng)成錨點(diǎn)。因?yàn)檫@樣會(huì)阻止迭代。
string.sub (s, i [, j])
返回 s 的子串, 該子串從 i 開始到 j 為止; i 和 j 都可以為負(fù)數(shù)。
string.gsub (s, pattern, repl [, n])
將字符串 s 中,所有的(或是在 n 給出時(shí)的前 n 個(gè)) pattern (參見 §6.4.1)都替換成 repl ,并返回其副本。 repl 可以是字符串、表、或函數(shù)。 gsub 還會(huì)在第二個(gè)返回值返回一共發(fā)生了多少次匹配。 這個(gè)和python中的re.sub有點(diǎn)類似。
如果 repl 是一個(gè)字符串,那么把這個(gè)字符串作為替換品。 字符 % 是一個(gè)轉(zhuǎn)義符: repl 中的所有形式為 %d 的串表示 第 d 個(gè)捕獲到的子串,d 可以是 1 到 9 。 串 %0 表示整個(gè)匹配。 串 %% 表示單個(gè) %。
如果 repl 是張表,每次匹配時(shí)都會(huì)用第一個(gè)捕獲物作為鍵去查這張表。
如果 repl 是個(gè)函數(shù),則在每次匹配發(fā)生時(shí)都會(huì)調(diào)用這個(gè)函數(shù)。 所有捕獲到的子串依次作為參數(shù)傳入。
這里有一些用例:
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)
接收一個(gè)字符串,返回其長度。 空串 "" 的長度為 0 。
string.lower (s)
接收一個(gè)字符串,將其中的大寫字符都轉(zhuǎn)為小寫后返回其副本。
string.upper (s)
string.pack (fmt, v1, v2, ···)
string.unpack (fmt, s [, pos])
返回一個(gè)打包了(即以二進(jìn)制形式序列化) v1, v2 等值的二進(jìn)制字符串。 字符串 fmt 為打包格式
string.rep (s, n [, sep])
返回 n 個(gè)字符串 s 以字符串 sep 為分割符連在一起的字符串。 默認(rèn)的 sep 值為空字符串(即沒有分割符)。
string.reverse (s)
返回字符串 s 的翻轉(zhuǎn)串。
Lua 中的匹配模式直接用常規(guī)的字符串來描述。 它用于模式匹配函數(shù) string.find, string.gmatch, string.gsub, string.match。
字符類:
字符類 用于表示一個(gè)字符集合。 下列組合可用于字符類:
x: (這里 x 不能是 魔法字符 ^$()%.[]*+-? 中的一員) 表示字符 x 自身。
.: (一個(gè)點(diǎn))可表示任何字符。
%a: 表示任何字母。
%c: 表示任何控制字符。
%d: 表示任何數(shù)字。
%g: 表示任何除空白符外的可打印字符。
%l: 表示所有小寫字母。
%p: 表示所有標(biāo)點(diǎn)符號(hào)。
%s: 表示所有空白字符。
%u: 表示所有大寫字母。
%w: 表示所有字母及數(shù)字。
%x: 表示所有 16 進(jìn)制數(shù)字符號(hào)。
%x: (這里的 x 是任意非字母或數(shù)字的字符) 表示字符 x。 這是對魔法字符轉(zhuǎn)義的標(biāo)準(zhǔn)方法。 所有非字母或數(shù)字的字符 (包括所有標(biāo)點(diǎn),也包括非魔法字符) 都可以用前置一個(gè) "%" 放在模式串中表示自身。
交叉使用類和范圍的行為未定義。 因此,像 [%a-z] 或 [a-%%] 這樣的模式串沒有意義。
所有單個(gè)字母表示的類別(%a,%c,等), 若將其字母改為大寫,均表示對應(yīng)的補(bǔ)集。 例如,%S 表示所有非空格的字符。
如何定義字母、空格、或是其他字符組取決于當(dāng)前的區(qū)域設(shè)置。 特別注意:[a-z] 未必等價(jià)于 %l 。
模式條目:
模式條目 可以是
單個(gè)字符類匹配該類別中任意單個(gè)字符;
單個(gè)字符類跟一個(gè) "*", 將匹配零或多個(gè)該類的字符。 這個(gè)條目總是匹配盡可能長的串;
單個(gè)字符類跟一個(gè) "+", 將匹配一或更多個(gè)該類的字符。 這個(gè)條目總是匹配盡可能長的串;
單個(gè)字符類跟一個(gè) "-", 將匹配零或更多個(gè)該類的字符。 和 "*" 不同, 這個(gè)條目總是匹配盡可能短的串;
單個(gè)字符類跟一個(gè) "?", 將匹配零或一個(gè)該類的字符。 只要有可能,它會(huì)匹配一個(gè);
%n, 這里的 n 可以從 1 到 9; 這個(gè)條目匹配一個(gè)等于 n 號(hào)捕獲物(后面有描述)的子串。
%bxy, 這里的 x 和 y 是兩個(gè)明確的字符; 這個(gè)條目匹配以 x 開始 y 結(jié)束, 且其中 x 和 y 保持 平衡 的字符串。 意思是,如果從左到右讀這個(gè)字符串,對每次讀到一個(gè) x 就 +1 ,讀到一個(gè) y 就 -1, 最終結(jié)束處的那個(gè) y 是第一個(gè)記數(shù)到 0 的 y。 舉個(gè)例子,條目 %b() 可以匹配到括號(hào)平衡的表達(dá)式。
%f[set], 指 邊境模式; 這個(gè)條目會(huì)匹配到一個(gè)位于 set 內(nèi)某個(gè)字符之前的一個(gè)空串, 且這個(gè)位置的前一個(gè)字符不屬于 set 。 集合 set 的含義如前面所述。 匹配出的那個(gè)空串之開始和結(jié)束點(diǎn)的計(jì)算就看成該處有個(gè)字符 "0" 一樣。
模式:
模式 指一個(gè)模式條目的序列。 在模式最前面加上符號(hào) "^" 將錨定從字符串的開始處做匹配。 在模式最后面加上符號(hào) "$" 將使匹配過程錨定到字符串的結(jié)尾。 如果 "^" 和 "$" 出現(xiàn)在其它位置,它們均沒有特殊含義,只表示自身。
捕獲:
模式可以在內(nèi)部用小括號(hào)括起一個(gè)子模式; 這些子模式被稱為 捕獲物。 當(dāng)匹配成功時(shí),由 捕獲物 匹配到的字符串中的子串被保存起來用于未來的用途。 捕獲物以它們左括號(hào)的次序來編號(hào)。 例如,對于模式 "(a(.)%w(%s))" , 字符串中匹配到 "a(.)%w(%s)" 的部分保存在第一個(gè)捕獲物中 (因此是編號(hào) 1 ); 由 "." 匹配到的字符是 2 號(hào)捕獲物, 匹配到 "%s*" 的那部分是 3 號(hào)。
作為一個(gè)特例,空的捕獲 () 將捕獲到當(dāng)前字符串的位置(它是一個(gè)數(shù)字)。 例如,如果將模式 "()aa()" 作用到字符串 "flaaap" 上,將產(chǎn)生兩個(gè)捕獲物: 3 和 5 。
UTF-8 支持這個(gè)庫提供了對 UTF-8 編碼的基礎(chǔ)支持。 所有的函數(shù)都放在表 utf8 中。
utf8.char (···)
接收零或多個(gè)整數(shù), 將每個(gè)整數(shù)轉(zhuǎn)換成對應(yīng)的 UTF-8 字節(jié)序列,并返回這些序列連接到一起的字符串。
utf8.charpattern
用于精確匹配到一個(gè) UTF-8 字節(jié)序列的模式(是一個(gè)字符串,并非函數(shù))"0-x7FxC2-xF4*"
utf8.len (s [, i [, j]])
返回字符串 s 中 從位置 i 到 j 間 (包括兩端) UTF-8 字符的個(gè)數(shù)。 默認(rèn)的 i 為 1 ,默認(rèn)的 j 為 -1 。
utf8.offset (s, n [, i])
返回編碼在 s 中的第 n 個(gè)字符的開始位置(按字節(jié)數(shù)) (從位置 i 處開始統(tǒng)計(jì))。
其余看文檔
表處理這個(gè)庫提供了表處理的通用函數(shù)。 所有函數(shù)都放在表 table 中。
table.concat (list [, sep [, i [, j]]])
返回字符串 list[i]..sep..list[i+1] ··· sep..list[j]。 sep 的默認(rèn)值是空串, i 的默認(rèn)值是 1 , j 的默認(rèn)值是 #list 。 如果 i 比 j 大,返回空串。
table.insert (list, [pos,] value)
在 list 的位置 pos 處插入元素 value , 并后移元素 list[pos], list[pos+1], ···, list[#list] 。 pos 的默認(rèn)值為 #list+1 , 因此調(diào)用 table.insert(t,x) 會(huì)將 x 插在列表 t 的末尾。
table.remove (list [, pos])
移除 list 中 pos 位置上的元素,并返回這個(gè)被移除的值。
table.sort (list [, comp])
在表內(nèi)從 list[1] 到 list[#list] 原地 對其間元素按指定次序排序。 如果提供了 comp , 它必須是一個(gè)可以接收兩個(gè)列表內(nèi)元素為參數(shù)的函數(shù)。 當(dāng)?shù)谝粋€(gè)元素需要排在第二個(gè)元素之前時(shí),返回真 (因此 not comp(list[i+1],list[i]) 在排序結(jié)束后將為真)。
table.pack (···)
返回用所有參數(shù)以鍵 1,2, 等填充的新表, 并將 "n" 這個(gè)域設(shè)為參數(shù)的總數(shù)。 注意這張返回的表不一定是一個(gè)序列。
table.unpack (list [, i [, j]])
返回列表中的元素。 這個(gè)函數(shù)等價(jià)于
return list[i], list[i+1], ···, list[j]
i 默認(rèn)為 1 ,j 默認(rèn)為 #list。
這個(gè)庫提供了基本的數(shù)學(xué)函數(shù)。 所以函數(shù)都放在表 math 中。
略。。。
I/O 庫提供了兩套不同風(fēng)格的文件處理接口。 第一種風(fēng)格使用隱式的文件句柄; 它提供設(shè)置默認(rèn)輸入文件及默認(rèn)輸出文件的操作, 所有的輸入輸出操作都針對這些默認(rèn)文件。 第二種風(fēng)格使用顯式的文件句柄。
當(dāng)使用隱式文件句柄時(shí), 所有的操作都由表 io 提供。 若使用顯式文件句柄, io.open 會(huì)返回一個(gè)文件句柄,且所有的操作都由該文件句柄的方法來提供。
表 io 中也提供了三個(gè) 和 C 中含義相同的預(yù)定義文件句柄: io.stdin, io.stdout, 以及 io.stderr。 I/O 庫永遠(yuǎn)不會(huì)關(guān)閉這些文件。
I/O 函數(shù)在出錯(cuò)時(shí)都返回 nil (第二個(gè)返回值為錯(cuò)誤消息,第三個(gè)返回值為系統(tǒng)相關(guān)的錯(cuò)誤碼)。 成功時(shí)返回與 nil 不同的值。
隱式文件句柄操作
io.close ([file])
等價(jià)于 file:close()。 不給出 file 時(shí)將關(guān)閉默認(rèn)輸出文件。
io.flush ()
io.lines ([filename ···])
以讀模式打開指定的文件名并返回一個(gè)迭代函數(shù)。 此迭代函數(shù)的工作方式和用一個(gè)已打開的文件去調(diào)用 file:lines(···) 得到的迭代器相同。 當(dāng)?shù)瘮?shù)檢測到文件結(jié)束, 它不返回值(讓循環(huán)結(jié)束)并自動(dòng)關(guān)閉文件。
調(diào)用 io.lines() (不傳文件名) 等價(jià)于 io.input():lines("*l"); 即,它將按行迭代標(biāo)準(zhǔn)輸入文件。 在此情況下,循環(huán)結(jié)束后它不會(huì)關(guān)閉文件。
io.open (filename [, mode])
這個(gè)函數(shù)用字符串 mode 指定的模式打開一個(gè)文件。 返回新的文件句柄。 當(dāng)出錯(cuò)時(shí),返回 nil 加錯(cuò)誤消息。
mode 字符串可以是下列任意值:
"r": 讀模式(默認(rèn));
"w": 寫模式;
"a": 追加模式;
"r+": 更新模式,所有之前的數(shù)據(jù)都保留;
"w+": 更新模式,所有之前的數(shù)據(jù)都刪除;
"a+": 追加更新模式,所有之前的數(shù)據(jù)都保留,只允許在文件尾部做寫入。
mode 字符串可以在最后加一個(gè) "b" , 這會(huì)在某些系統(tǒng)上以二進(jìn)制方式打開文件。
io.popen (prog [, mode])
這個(gè)函數(shù)和系統(tǒng)有關(guān),不是所有的平臺(tái)都提供。
用一個(gè)分離進(jìn)程開啟程序 prog, 返回的文件句柄可用于從這個(gè)程序中讀取數(shù)據(jù) (如果 mode 為 "r",這是默認(rèn)值) 或是向這個(gè)程序?qū)懭胼斎耄ó?dāng) mode 為 "w" 時(shí))。
io.input ([file])
用文件名調(diào)用它時(shí),(以文本模式)來打開該名字的文件, 并將文件句柄設(shè)為默認(rèn)輸入文件。 如果用文件句柄去調(diào)用它, 就簡單的將該句柄設(shè)為默認(rèn)輸入文件。 如果調(diào)用時(shí)不傳參數(shù),它返回當(dāng)前的默認(rèn)輸入文件。
io.read (···)
等價(jià)于 io.input():read(···)。
io.tmpfile ()
返回一個(gè)臨時(shí)文件的句柄。 這個(gè)文件以更新模式打開,在程序結(jié)束時(shí)會(huì)自動(dòng)刪除。
io.type (obj)
檢查 obj 是否是合法的文件句柄。 如果 obj 它是一個(gè)打開的文件句柄,返回字符串 "file"。 如果 obj 是一個(gè)關(guān)閉的文件句柄,返回字符串 "closed file"。 如果 obj 不是文件句柄,返回 nil 。
io.output ([file])
類似于 io.input。 不過都針對默認(rèn)輸出文件操作。
io.write (···)
等價(jià)于 io.output():write(···)。
顯式文件句柄操作
若使用顯式文件句柄, io.open 會(huì)返回一個(gè)文件句柄
file:close ()
關(guān)閉 file。
file:flush ()
將寫入的數(shù)據(jù)保存到 file 中。
file:lines (···)
返回一個(gè)迭代器函數(shù), 每次調(diào)用迭代器時(shí),都從文件中按指定格式讀數(shù)據(jù)。 如果沒有指定格式,使用默認(rèn)值 "l" 。 看一個(gè)例子
for c in file:lines(1) do body end
會(huì)從文件當(dāng)前位置開始,中不斷讀出字符。 和 io.lines 不同, 這個(gè)函數(shù)在循環(huán)結(jié)束后不會(huì)關(guān)閉文件。
file:read (···)
讀文件 file, 指定的格式?jīng)Q定了要讀什么。 對于每種格式,函數(shù)返回讀出的字符對應(yīng)的字符串或數(shù)字。 若不能以該格式對應(yīng)讀出數(shù)據(jù)則返回 nil。 (對于最后這種情況, 函數(shù)不會(huì)讀出后續(xù)的格式。) 當(dāng)調(diào)用時(shí)不傳格式,它會(huì)使用默認(rèn)格式讀下一行(見下面描述)。
提供的格式有
"n": 讀取一個(gè)數(shù)字,根據(jù) Lua 的轉(zhuǎn)換文法,可能返回浮點(diǎn)數(shù)或整數(shù)。 (數(shù)字可以有前置或后置的空格,以及符號(hào)。) 只要能構(gòu)成合法的數(shù)字,這個(gè)格式總是去讀盡量長的串; 如果讀出來的前綴無法構(gòu)成合法的數(shù)字 (比如空串,"0x" 或 "3.4e-"), 就中止函數(shù)運(yùn)行,返回 nil。
"i": 讀取一個(gè)整數(shù),返回整數(shù)值。
"a": 從當(dāng)前位置開始讀取整個(gè)文件。 如果已在文件末尾,返回空串。
"l": 讀取一行并忽略行結(jié)束標(biāo)記。 當(dāng)在文件末尾時(shí),返回 nil 這是默認(rèn)格式。
"L": 讀取一行并保留行結(jié)束標(biāo)記(如果有的話), 當(dāng)在文件末尾時(shí),返回 nil。
number: 讀取一個(gè)不超過這個(gè)數(shù)量字節(jié)數(shù)的字符串。 當(dāng)在文件末尾時(shí),返回 nil。 如果 number 為零, 它什么也不讀,返回一個(gè)空串。 當(dāng)在文件末尾時(shí),返回 nil。
格式 "l" 和 "L" 只能用于文本文件。
file:seek ([whence [, offset]])
設(shè)置及獲取基于文件開頭處計(jì)算出的位置。 設(shè)置的位置由 offset 和 whence 字符串 whence 指定的基點(diǎn)決定?;c(diǎn)可以是:
"set": 基點(diǎn)為 0 (文件開頭);
"cur": 基點(diǎn)為當(dāng)前位置了;
"end": 基點(diǎn)為文件尾;
當(dāng) seek 成功時(shí),返回最終從文件開頭計(jì)算起的文件的位置。 當(dāng) seek 失敗時(shí),返回 nil 加上一個(gè)錯(cuò)誤描述字符串。
whence 的默認(rèn)值是 "cur", offset 默認(rèn)為 0 。 因此,調(diào)用 file:seek() 可以返回文件當(dāng)前位置,并不改變它; 調(diào)用 file:seek("set") 將位置設(shè)為文件開頭(并返回 0); 調(diào)用 file:seek("end") 將位置設(shè)到文件末尾,并返回文件大小。
file:setvbuf (mode [, size])
設(shè)置輸出文件的緩沖模式。 有三種模式:
"no": 不緩沖;輸出操作立刻生效。
"full": 完全緩沖;只有在緩存滿或當(dāng)你顯式的對文件調(diào)用 flush(參見 io.flush) 時(shí)才真正做輸出操作。
"line": 行緩沖; 輸出將到每次換行前, 對于某些特殊文件(例如終端設(shè)備)緩沖到任何輸入前。
對于后兩種情況,size 以字節(jié)數(shù)為單位 指定緩沖區(qū)大小。 默認(rèn)會(huì)有一個(gè)恰當(dāng)?shù)拇笮 ?/p>
file:write (···)
將參數(shù)的值逐個(gè)寫入 file。 參數(shù)必須是字符串或數(shù)字。
成功時(shí),函數(shù)返回 file。 否則返回 nil 加錯(cuò)誤描述字符串。
這個(gè)庫都通過表 os 實(shí)現(xiàn)。
os.clock ()
返回程序使用的按秒計(jì) CPU 時(shí)間的近似值。
os.date ([format [, time]])
返回一個(gè)包含日期及時(shí)刻的字符串或表。 格式化方法取決于所給字符串 format。
如果提供了 time 參數(shù), 格式化這個(gè)時(shí)間 (這個(gè)值的含義參見 os.time 函數(shù))。 否則,date 格式化當(dāng)前時(shí)間。
如果 format 以 "!" 打頭, 日期以協(xié)調(diào)世界時(shí)格式化。 在這個(gè)可選字符項(xiàng)之后, 如果 format 為字符串 "*t", date 返回有后續(xù)域的表: year (四位數(shù)字),month (1–12),day (1–31), hour (0–23),min (0–59),sec (0–61), wday (星期幾,星期天為 1 ), yday (當(dāng)年的第幾天), 以及 isdst (夏令時(shí)標(biāo)記,一個(gè)布爾量)。 對于最后一個(gè)域,如果該信息不提供的話就不存在。
如果 format 并非 "*t", date 以字符串形式返回, 格式化方法遵循 ISO C 函數(shù) strftime 的規(guī)則。
os.difftime (t2, t1)
返回以秒計(jì)算的時(shí)刻 t1 到 t2 的差值。 (這里的時(shí)刻是由 os.time 返回的值)。
os.execute ([command])
它調(diào)用系統(tǒng)解釋器執(zhí)行 command。 如果命令成功運(yùn)行完畢,第一個(gè)返回值就是 true, 否則是 nil。 在第一個(gè)返回值之后,函數(shù)返回一個(gè)字符串加一個(gè)數(shù)字。如下:
"exit": 命令正常結(jié)束; 接下來的數(shù)字是命令的退出狀態(tài)碼。
"signal": 命令被信號(hào)打斷; 接下來的數(shù)字是打斷該命令的信號(hào)。
os.exit ([code [, close]])
調(diào)用 ISO C 函數(shù) exit 終止宿主程序。 如果 code 為 true, 返回的狀態(tài)碼是 EXIT_SUCCESS; 如果 code 為 false, 返回的狀態(tài)碼是 EXIT_FAILURE; 如果 code 是一個(gè)數(shù)字, 返回的狀態(tài)碼就是這個(gè)數(shù)字。 code 的默認(rèn)值為 true。
os.getenv (varname)
返回進(jìn)程環(huán)境變量 varname 的值, 如果該變量未定義,返回 nil 。
os.remove (filename)
刪除指定名字的文件(在 POSIX 系統(tǒng)上可以是一個(gè)空目錄) 如果函數(shù)失敗,返回 nil 加一個(gè)錯(cuò)誤描述串及出錯(cuò)碼。
os.rename (oldname, newname)
將名字為 oldname 的文件或目錄更名為 newname。 如果函數(shù)失敗,返回 nil 加一個(gè)錯(cuò)誤描述串及出錯(cuò)碼。
os.time ([table])
當(dāng)不傳參數(shù)時(shí),返回當(dāng)前時(shí)刻。 如果傳入一張表,就返回由這張表表示的時(shí)刻。 這張表必須包含域 year,month,及 day; 可以包含有 hour (默認(rèn)為 12 ), min (默認(rèn)為 0), sec (默認(rèn)為 0),以及 isdst (默認(rèn)為 nil)。
這個(gè)庫里的所有函數(shù)都提供在表 debug 內(nèi)。 所有操作線程的函數(shù),可選的第一個(gè)參數(shù)都是針對的線程。 默認(rèn)值永遠(yuǎn)是當(dāng)前線程。
debug.traceback ([thread,] [message [, level]])
如果 message 有,且不是字符串或 nil, 函數(shù)不做任何處理直接返回 message。 否則,它返回調(diào)用棧的棧回溯信息。 字符串可選項(xiàng) message 被添加在?;厮菪畔⒌拈_頭。 數(shù)字可選項(xiàng) level 指明從棧的哪一層開始回溯 (默認(rèn)為 1 ,即調(diào)用 traceback 的那里)。
其他,請看文檔
雖然 Lua 被設(shè)計(jì)成一門擴(kuò)展式語言,用于嵌入一個(gè)宿主程序。 但經(jīng)常也會(huì)被當(dāng)成獨(dú)立語言使用。 獨(dú)立版的 Lua 語言解釋器隨標(biāo)準(zhǔn)包發(fā)布,就叫 lua。 其命令行用法為:
lua [options] [script [args]]
選項(xiàng)有:
-e stat: 執(zhí)行一段字符串 stat ; -l mod: “請求模塊” mod ; -i: 在運(yùn)行完 腳本 后進(jìn)入交互模式; -v: 打印版本信息; -E: 忽略環(huán)境變量; --: 中止對后面選項(xiàng)的處理; -: 把 stdin 當(dāng)作一個(gè)文件運(yùn)行,并中止對后面選項(xiàng)的處理。
在處理完選項(xiàng)后,lua 運(yùn)行指定的 腳本。 如果不帶參數(shù)調(diào)用, 在標(biāo)準(zhǔn)輸入(stdin)是終端時(shí),lua 的行為和 lua -v -i 相同。 否則相當(dāng)于 lua - 。
為了讓 Lua 可以用于 Unix 系統(tǒng)的腳本解釋器。
!/usr/local/bin/lua如果 lua 在你的 PATH 中, 寫成 #!/usr/bin/env lua更為通用。
與之前版本(5.2)不兼容的地方該版本主要實(shí)現(xiàn)了對整數(shù)、位操作、UTF-8 的支持以及打包和解包的功能。
Lua 5.2 到 Lua 5.3 最大的變化是引入了數(shù)字的整數(shù)子類型,你可以通過把數(shù)字都強(qiáng)制轉(zhuǎn)換為浮點(diǎn)數(shù)來消除差異 (在 Lua 5.2 中,所有的數(shù)字都是浮點(diǎn)數(shù))。
bit32 庫廢棄了。 使用一個(gè)外部兼容庫很容易, 不過最好直接用對應(yīng)的位操作符來替換它。 (注意 bit32 只能針對 32 位整數(shù)運(yùn)算, 而標(biāo)準(zhǔn) Lua 中的位操作可以用于 64 位整數(shù)。)
io.read 的選項(xiàng)名不再用 "*" 打頭。 但出于兼容性考慮,Lua 會(huì)繼續(xù)忽略掉這個(gè)字符。
數(shù)學(xué)庫中的這些函數(shù)廢棄了: atan2, cosh, sinh, tanh, pow, frexp, 以及 ldexp 。 你可以用 x^y 替換 math.pow(x,y);
require 在搜索 C 加載器時(shí)處理版本號(hào)的方式有所變化。 現(xiàn)在,版本號(hào)應(yīng)該跟在模塊名后(其它大多數(shù)工具都是這樣干的)。 出于兼容性考慮,如果使用新格式找不到加載器的話,搜索器依然會(huì)嘗試舊格式。
可以參考:http://blog.codingnow.com/201...
http://blog.csdn.net/weiyuefe...
5.1 與 5.2 是完全不兼容的,相關(guān)的第三方庫必須重新為 5.2 適配。
luajit不支持5.2,5.3
具體見
http://www.lua.org/manual/5.2...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/39421.html
摘要:多返回值開始變得越來越與眾不同了允許函數(shù)返回多個(gè)結(jié)果。這種情況函數(shù)沒有足夠的返回值時(shí)也會(huì)用來補(bǔ)充。中的索引習(xí)慣以開始。 showImg(https://segmentfault.com/img/bVIcQU?w=136&h=103); 為什么值得入手? Nginx作為現(xiàn)在使用最廣泛的高性能后端服務(wù)器,Openresty為之提供了動(dòng)態(tài)預(yù)言的靈活,當(dāng)性能與靈活走在了一起,無疑對于被之前陷于...
閱讀 2765·2021-10-09 09:44
閱讀 3564·2019-08-30 15:54
閱讀 2174·2019-08-30 14:16
閱讀 2804·2019-08-30 13:09
閱讀 838·2019-08-30 13:08
閱讀 1297·2019-08-29 16:29
閱讀 1686·2019-08-26 13:57
閱讀 1942·2019-08-26 13:53