




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領
文檔簡介
1、Lua 5.1 參考手冊 by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes 云風 譯 Copyright © 2006 L, PUC-Rio. All rights reserved. 1 - 介紹Lua 是一個擴展式程序設計語言,它被設計成支持通用的過程式編程,并有相關數(shù)據(jù)描述的設施。 Lua 也能對面向?qū)ο缶幊?,函?shù)式編程,數(shù)據(jù)驅(qū)動式編程提供很好的支持。它可以作為一個強大、輕量的腳本語言,供任何需要的程序使用。 Lua 以一個用 clean C 寫成的庫形式提供。(所謂 Clea
2、n C ,指的 ANSI C 和 C+ 中共通的一個子集) 作為一個擴展式語言,Lua 沒有 "main" 程序的概念:它只能 嵌入 一個宿主程序中工作,這個宿主程序被稱作 embedding program 或簡稱為 host 。宿主程序可以通過調(diào)用函數(shù)執(zhí)行一小段 Lua 代碼,可以讀寫 Lua 變量,可以注入 C 函數(shù)讓 Lua 代碼調(diào)用。這些擴展的 C 函數(shù),可以大大的擴展了 Lua 可以處理事務的領域,這樣就可以訂制出各種語言,而它們共享一個統(tǒng)一的句法格式的框架。 Lua 的官方發(fā)布版就包含了一個叫做 lua 的簡單的宿主程序,它用 Lua 庫提供了一個保證獨立的
3、Lua 解釋器。 Lua 是一個自由軟件,它的使用許可決定了對它的使用過程一般沒有任何保證。這份手冊中描述的東西的實現(xiàn),可以在 Lua 的官方網(wǎng)站 找到, 跟其它的許多參考手冊一樣,這份文檔有些地方比較枯燥。關于 Lua 的設計想法的探討,可以看看 Lua 網(wǎng)站上提供的技術論文。有關用 Lua 編程的細節(jié)介紹,可以讀一下 Roberto 的書,Programming in Lua (Second Edition) 。 2 - 語言這一節(jié)從詞法、語法、句法上描述 Lua 。換句話說,這一節(jié)描述了哪些 token (符記)是有效的,它們?nèi)绾伪唤M合起來,這些組合方式有什么含義
4、。 關于語言的構(gòu)成概念將用常見的擴展 BNF 表達式寫出。也就是這個樣子: a 意思是 0 或多個 a , a 意思是一個可選的 a 。非最終的符號會保留原來的樣子,關鍵字則看起來像這樣 kword ,其它最終的符號則寫成 =´ 。完整的 Lua 語法可以在本手冊最后找到。 2.1 - 詞法約定Lua 中用到的 名字(也稱作 標識符)可以是任何非數(shù)字開頭的字母、數(shù)字、下劃線組成的字符串。這符合幾乎所有編程語言中關于名字的定義。(字母的定義依賴于當前環(huán)境:系統(tǒng)環(huán)境中定義的字母表中的字母都可以被用于標識符。)標識符用來命名變量,或作為表的域名。 下面的關鍵字是保留的,不能用作名字: an
5、d break do else elseif end false for function if in local nil not or repeat return then true until whileLua 是一個大小寫敏感的語言: and 是一個保留字,但是 And 和 AND 則是兩個不同的合法的名字。一般約定,以下劃線開頭連接一串大寫字母的名字(比如 _VERSION)被保留用于 Lua 內(nèi)部全局變量。 下面這些是其它的 token : + - * / % # = = <= >= < > = ( ) ; : , . . .字符串既可以用一對單引號引起,也可
6、以是雙引號,里面還可以包含類似 C 的轉(zhuǎn)義符: 'a' (響鈴), 'b' (退格), 'f' (表單), 'n' (換行), 'r' (回車), 't' (橫向制表), 'v' (縱向制表), '' (反斜杠), '"' (雙引號),以及 ''' (單引號)。而且,如果在一個反斜杠后跟了一個真正的換行符,其結(jié)果就是在字符串中產(chǎn)生一個換行符。我們還可以用反斜杠加數(shù)字的形式 ddd 來描述一個字符。這里, ddd 是一串
7、最多三位的十進制數(shù)字。(注意,如果需要在這種描述方法后接一個是數(shù)字的字符,那么反斜杠后必須寫滿三個數(shù)字。)Lua 中的字符串可以包含任何 8 位的值。包括用 '0' 表示的零。 只有在你需要把不同的引號、換行、反斜杠、或是零結(jié)束符這些字符置入字符串時,你才必須使用轉(zhuǎn)義符。別的任何字符都可以直接寫在文本里。(一些控制符可以會影響文件系統(tǒng)造成某些問題,但是不會引起 Lua 的任何問題。) 字符串還可以用一種長括號括起來的方式定義。我們把兩個正的方括號間插入 n 個等號定義為第 n 級正長括號。就是說,0 級正的長括號寫作 ,一級正的長括號寫作 = ,如此等等。反的長擴展也作類似定義
8、;舉個例子,4 級反的長括號寫作 = 。一個長字符串可以由任何一級的正的長括號開始,而由第一個碰到的同級反的長括號結(jié)束。整個詞法分析過程將不受分行限制,不處理任何轉(zhuǎn)意符,并且忽略掉任何不同級別的長括號。這種方式描述的字符串可以包含任何東西,當然特定級別的反長括號除外。 另一個約定是,當正的長括號后面立即跟了一個換行符,這個換行符就不包含在這個字符串內(nèi)。舉個例子,假設一個系統(tǒng)使用 ASCII 碼(這時,'a' 編碼為 97 ,換行符編碼為 10 ,'1' 編碼為 49 ),下面五種方式描述了完全相同的字符串: a = 'alon123"'
9、 a = "alon123"" a = '97lo1004923"' a = alo 123" a = = alo 123"=數(shù)字常量可以分兩部分寫,十進制底數(shù)部分和十進制的指數(shù)部分。指數(shù)部分是可選的。 Lua 也支持十六進制整數(shù)常量,只需要在前面加上前綴 0x 。下面是一些合法的數(shù)字常量的例子: 3 3.0 3.1416 314.16e-2 0.31416E1 0xff 0x56注釋可以在除字符串內(nèi)的任何地方是以兩橫 (-) 開始。如果跟在兩橫后面的不是一個長括號,這就是一個短注釋,它的作用范圍直到行末;否則就是一個
10、長注釋,其作用范圍直到遇到反的長括號。長注釋通常被用來臨時屏蔽代碼塊。 2.2 - 值與類型Lua 是一種 動態(tài)類型語言。這意味著變量沒有類型,只有值才有類型。語言中不存在類型定義。而所有的值本身攜帶它們自己的類型信息。 Lua 中的所有值都是一致 (first-class) 的。這意味著所有的值都可以被放在變量里,當作參數(shù)傳遞到另一個函數(shù)中,并被函數(shù)作為結(jié)果返回。 Lua 中有八種基本類型: nil, boolean, number, string, function, userdata, thread, and table. Nil 類型只有一種值 nil ,它的主要用途用于標表識和別的任
11、何值的差異;通常,當需要描述一個無意義的值時會用到它。 Boolean 類型只有兩種值:false 和 true。 nil 和 false 都能導致條件為假;而另外所有的值都被當作真。 Number 表示實數(shù)(雙精度浮點數(shù))。(編譯一個其它內(nèi)部數(shù)字類型的 Lua 解釋器是件很容易的事;比如把內(nèi)部數(shù)字類型改作單精度浮點數(shù)或長整型。參見文件 luaconf.h 。) String 表示一串字符的數(shù)組。 Lua 是 8-bit clean 的:字符串可以包含任何 8 位字符,包括零結(jié)束符 ('0') (參見 §2.1)。 Lua 可以調(diào)用(和處理)用 Lua 寫的函數(shù)以及用
12、 C 寫的函數(shù)(參見 §2.5.8). userdata 類型用來將任意 C 數(shù)據(jù)保存在 Lua 變量中。這個類型相當于一塊原生的內(nèi)存,除了賦值和相同性判斷,Lua 沒有為之預定義任何操作。然而,通過使用 metatable (元表) ,程序員可以為 userdata 自定義一組操作(參見 §2.8)。 userdata 不能在 Lua 中創(chuàng)建出來,也不能在 Lua 中修改。這樣的操作只能通過 C API。這一點保證了宿主程序完全掌管其中的數(shù)據(jù)。 thread 類型用來區(qū)別獨立的執(zhí)行線程,它被用來實現(xiàn) coroutine (協(xié)同例程)(參見 §2.11)。不要把
13、Lua 線程跟操作系統(tǒng)的線程搞混。 Lua 可以在所有的系統(tǒng)上提供對 coroutine 的支持,即使系統(tǒng)并不支持線程。 table 類型實現(xiàn)了一個關聯(lián)數(shù)組。也就是說,數(shù)組可以用任何東西(除了nil)做索引,而不限于數(shù)字。 table 可以以不同類型的值構(gòu)成;它可以包含所有的類型的值(除 nil 外)。 table 是 lua 中唯一的一種數(shù)據(jù)結(jié)構(gòu);它可以用來描述原始的數(shù)組、符號表、集合、記錄、圖、樹、等等。用于表述記錄時,lua 使用域名作為索引。語言本身采用一種語法糖,支持以 的形式表示 a"name"。有很多形式用于在 lua 中創(chuàng)建一個 table (
14、參見 §2.5.7)。 跟索引一樣, table 每個域中的值也可以是任何類型(除 nil外)。特別的,因為函數(shù)本身也是值,所以 table 的域中也可以放函數(shù)。這樣 table 中就可以有一些 methods 了 (參見see §2.5.9)。 table, function ,thread ,和 (full) userdata 這些類型的值是所謂的對象:變量本身并不會真正的存放它們的值,而只是放了一個對對象的引用。賦值,參數(shù)傳遞,函數(shù)返回,都是對這些對象的引用進行操作;這些操作不會做暗地里做任何性質(zhì)的拷貝。 庫函數(shù) type 可以返回一個描述給定值的類型的字符串。 2.
15、2.1 - 強制轉(zhuǎn)換Lua 提供運行時字符串到數(shù)字的自動轉(zhuǎn)換。任何對字符串的數(shù)學運算操作都會嘗試用一般的轉(zhuǎn)換規(guī)則把這個字符串轉(zhuǎn)換成一個數(shù)字。相反,無論何時,一個數(shù)字需要作為字符串來使用時,數(shù)字都會以合理的格式轉(zhuǎn)換為字符串。需要完全控制數(shù)字怎樣轉(zhuǎn)換為字符串,可以使用字符串庫中的 format 函數(shù)(參見 string.format)。 2.3 - 變量寫上變量的地方意味著當以其保存的值來替代之。 Lua 中有三類變量:全局變量,局部變量,還有 table 的域。 一個單一的名字可以表示一個全局變量,也可以表示一個局部變量 (或者是一個函數(shù)的參數(shù),這是一種特殊形式的局部變量): var := Na
16、meName 就是 §2.1 中所定義的標識符。 任何變量都被假定為全局變量,除非顯式的以 local 修飾定義 (參見 §2.4.7)。局部變量有其作用范圍:局部變量可以被定義在它作用范圍中的函數(shù)自由使用(參見 §2.6)。 在變量的首次賦值之前,變量的值均為 nil。 方括號被用來對 table 作索引: var := prefixexp ´ exp ´對全局變量以及 table 域之訪問的含義可以通過 metatable 來改變。以取一個變量下標指向的量 ti 等價于調(diào)用 gettable_event(t,i)。(參見 §2.8
17、 ,有一份完整的關于 gettable_event 函數(shù)的說明。這個函數(shù)并沒有在 lua 中定義出來,也不能在 lua 中調(diào)用。這里我們把它列出來只是方便說明。) var.Name 這種語法只是一個語法糖,用來表示 var"Name": var := prefixexp .´ Name所有的全局變量都是放在一個特定 lua table 的諸個域中,這個特定的 table 叫作 environment (環(huán)境)table 或者簡稱為 環(huán)境 (參見 §2.9)。每個函數(shù)都有對一個環(huán)境的引用,所以一個函數(shù)中可見的所有全局變量都放在這個函數(shù)所引用的環(huán)境表(env
18、ironment table)中。當一個函數(shù)被創(chuàng)建出來,它會從創(chuàng)建它的函數(shù)中繼承其環(huán)境,你可以調(diào)用 getfenv 取得其環(huán)境。如果想改變環(huán)境,可以調(diào)用 setfenv。(對于 C 函數(shù),你只能通過 debug 庫來改變其環(huán)境;參見 §5.9)。 對一個全局變量 x 的訪問等價于 _env.x,而這又可以等價于 gettable_event(_env, "x")這里,_env 是當前運行的函數(shù)的環(huán)境。(函數(shù) gettable_event 的完整說明參見 §2.8。這個函數(shù)并沒有在 lua 中定義出來,也不能調(diào)用。當然,_env 這個變量也同樣沒有在 Lu
19、a 中定義出來。我們在這里使用它們,僅僅只是方便解釋而已。) 2.4 - 語句段(Statement)Lua 支持慣例形式的語句段,它和 Pascal 或是 C 很相象。這個集合包括賦值,控制結(jié)構(gòu),函數(shù)調(diào)用,還有變量聲明。 2.4.1 - Chunk(語句組)Lua 的一個執(zhí)行單元被稱作 chunk。一個 chunk 就是一串語句段,它們會被循序的執(zhí)行。每個語句段可以以一個分號結(jié)束: chunk := stat ;´這兒不允許有空的語句段,所以 '' 是非法的。 lua 把一個 chunk 當作一個擁有不定參數(shù)的匿名函數(shù)(參見 §2.5.9)處理。正是這樣,
20、chunk 內(nèi)可以定義局部變量,接收參數(shù),并且返回值。 chunk 可以被保存在一個文件中,也可以保存在宿主程序的一個字符串中。當一個 chunk 被執(zhí)行,首先它會被預編譯成虛擬機中的指令序列,然后被虛擬機解釋運行這些指令。 chunk 也可以被預編譯成二進制形式;細節(jié)參考程序 luac。用源碼形式提供的程序和被編譯過的二進制形式的程序是可以相互替換的; Lua 會自動識別文件類型并做正確的處理。 2.4.2 - 語句塊語句塊是一列語句段;從語法上來說,一個語句塊跟一個 chunk 相同: block := chunk一個語句塊可以被顯式的寫成一個單獨的語句段: stat := do bloc
21、k end顯式的語句塊對于控制變量的作用范圍很有用。有時候,顯式的語句塊被用來在另一個語句塊中插入 return 或是 break (參見 §2.4.4)。 2.4.3 - 賦值Lua 允許多重賦值。因此,賦值的語法定義是等號左邊放一系列變量,而等號右邊放一系列的表達式。兩邊的元素都用逗號間開: stat := varlist1 =´ explist1varlist1 := var ,´ varexplist1 := exp ,´ exp表達式放在 §2.5 里討論。 在作賦值操作之前,那一系列的右值會被對齊到左邊變量需要的個數(shù)。如果右值比需要
22、的更多的話,多余的值就被扔掉。如果右值的數(shù)量不夠需求,將會按所需擴展若干個 nil。如果表達式列表以一個函數(shù)調(diào)用結(jié)束,這個函數(shù)所返回的所有值都會在對齊操作之前被置入右值序列中。(除非這個函數(shù)調(diào)用被用括號括了起來;參見 §2.5)。 賦值段首先會做運算完所有的表達式,然后僅僅做賦值操作。因此,下面這段代碼 i = 3 i, ai = i+1, 20會把 a3 設置為 20,而不會影響到 a4 。這是因為 ai 中的 i 在被賦值為 4 之前就被拿出來了(那時是 3 )。簡單說 ,這樣一行 x, y = y, x可以用來交換 x 和 y 中的值。 對全局變量以及 table 中的域的賦值
23、操作的含義可以通過 metatable 來改變。對變量下標指向的賦值,即 ti = val 等價于 settable_event(t,i,val)。(關于函數(shù) settable_event 的詳細說明,參見 §2.8。這個函數(shù)并沒有在 Lua 中定義出來,也不可以被調(diào)用。這里我們列出來,僅僅出于方便解釋的目的) 對于全局變量的賦值 x = val 等價于 _env.x = val,這個又可以等價于 settable_event(_env, "x", val)這里,_env 指的是正在運行中的函數(shù)的環(huán)境。(變量 _env 并沒有在 Lua 中定義出來。我們僅僅出于解
24、釋的目的在這里寫出來。) 2.4.4 - 控制結(jié)構(gòu)if、 while、以及 repeat 這些控制結(jié)構(gòu)符合通常的意義,而且也有類似的語法: stat := while exp do block endstat := repeat block until expstat := if exp then block elseif exp then block else block endLua 也有一個 for 語句,它有兩種形式(參見 §2.4.5)。 控制結(jié)構(gòu)中的條件表達式可以返回任何值。 false 和 nil 兩者都被認為是假條件。所有不同于 nil 和 false 的其它值都被認
25、為是真(特別需要注意的是,數(shù)字 0 和空字符串也被認為是真)。 在 repeatuntil 循環(huán)中,內(nèi)部語句塊的結(jié)束點不是在 until 這個關鍵字處,它還包括了其后的條件表達式。因此,條件表達式中可以使用循環(huán)內(nèi)部語句塊中的定義的局部變量。 return 被用于從函數(shù)或是 chunk(其實它就是一個函數(shù))中返回值。 函數(shù)和 chunk 可以返回不只一個值,所以 return 的語法為 stat := return explist1break 被用來結(jié)束 while、 repeat、或 for 循環(huán),它將忽略掉循環(huán)中下面的語句段的運行: stat := breakbreak 跳出最內(nèi)層的循環(huán)。
26、return 和 break 只能被寫在一個語句塊的最后一句。如果你真的需要從語句塊的中間 return 或是 break ,你可以使用顯式的聲名一個內(nèi)部語句塊。一般寫作 do return end 或是 do break end,可以這樣寫是因為現(xiàn)在 return 或 break 都成了一個語句塊的最后一句了。 2.4.5 - For 語句for 有兩種形式:一種是數(shù)字形式,另一種是一般形式。 數(shù)字形式的 for 循環(huán),通過一個數(shù)學運算不斷的運行內(nèi)部的代碼塊。下面是它的語法: stat := for Name =´ exp ,´ exp ,´ exp do bl
27、ock endblock 將把 name 作循環(huán)變量。從第一個 exp 開始起,直到第二個 exp 的值為止,其步長為第三個 exp 。更確切的說,一個 for 循環(huán)看起來是這個樣子 for v = e1, e2, e3 do block end這等價于代碼: do local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3) if not (var and limit and step) then error() end while (step > 0 and var <= limit) or (step &l
28、t;= 0 and var >= limit) do local v = var block var = var + step end end注意下面這幾點: · 所有三個控制表達式都只被運算一次,表達式的計算在循環(huán)開始之前。這些表達式的結(jié)果必須是數(shù)字。 · var 、limit 、以及 step 都是一些不可見的變量。這里給它們起的名字都僅僅用于解釋方便。 · 如果第三個表達式(步長)沒有給出,會把步長設為 1 。 · 你可以用 break 來退出 for 循環(huán)。 · 循環(huán)變量 v 是一個循環(huán)內(nèi)部的局部變量;當 for 循環(huán)結(jié)束后,你就
29、不能在使用它。如果你需要這個值,在退出循環(huán)前把它賦給另一個變量。 一般形式的 for 通過一個叫作迭代器(iterators)的函數(shù)工作。每次迭代,迭代器函數(shù)都會被調(diào)用以產(chǎn)生一個新的值,當這個值為 nil 時,循環(huán)停止。一般形式的 for 循環(huán)的語法如下: stat := for namelist in explist1 do block endnamelist := Name ,´ Namefor 語句好似這樣 for var_1, ···, var_n in explist do block end它等價于這樣一段代碼: do local f, s,
30、 var = explist while true do local var_1, ···, var_n = f(s, var) var = var_1 if var = nil then break end block end end注意以下幾點: · explist 只會被計算一次。它返回三個值, 一個迭代器函數(shù),一個狀態(tài),一個迭代器的初始值。 · f、 s、 以及 var 都是不可見的變量。這里給它們起的名字都只是為了解說方便。 · 你可以使用 break 來跳出 for 循環(huán)。 · 循環(huán)變量 var_i 對于循環(huán)來說
31、是一個局部變量;你不可以在 for 循環(huán)結(jié)束后繼續(xù)使用。如果你需要保留這些值,那么就在循環(huán)結(jié)束前賦值到別的變量里去。 2.4.6 - 把函數(shù)調(diào)用作為語句段為了允許使用可能的副作用,函數(shù)調(diào)用可以被作為一個語句段執(zhí)行: stat := functioncall在這種情況下,所有的返回值都被舍棄。函數(shù)調(diào)用在 §2.5.8 中解釋。 2.4.7 - 局部變量聲名局部變量可以在語句塊中任何地方聲名。聲名可以包含一個初始化賦值操作: stat := local namelist =´ explist1如果有的話,初始化賦值操作的行為等同于賦值操作(參見 §2.4.3)。否則,
32、所有的變量將被初始化為 nil。 一個 chunk 同時也是一個語句塊(參見 §2.4.1),所以局部變量可以放在 chunk 中那些顯式注明的語句塊之外。這些局部變量的作用范圍從聲明起一直延伸到 chunk 末尾。 局部變量的可見規(guī)則在 §2.6 中解釋。 2.5 - 表達式Lua 中有這些基本表達式: exp := prefixexpexp := nil | false | trueexp := Numberexp := Stringexp := functionexp := tableconstructorexp := .´exp := exp binop
33、expexp := unop expprefixexp := var | functioncall | (´ exp )´數(shù)字和字符串在 §2.1 中解釋;變量在 §2.3 中解釋;函數(shù)定義在 §2.5.9 中解釋;函數(shù)調(diào)用在 §2.5.8 中解釋; table 的構(gòu)造在 §2.5.7 中解釋;可變參數(shù)的表達式寫作三個點 ('.') ,它只能被用在有可變參數(shù)的函數(shù)中;這些在 §2.5.9 中解釋。 二元操作符包含有數(shù)學運算操作符(參見 §2.5.1),比較操作符(參見 §2.5.
34、2),邏輯操作符(參見 §2.5.3),以及連接操作符(參見 §2.5.4)。一元操作符包括負號(參見see §2.5.1),取反 not(參見 §2.5.3),和取長度操作符(參見 §2.5.5)。 函數(shù)調(diào)用和可變參數(shù)表達式都可以放在多重返回值中。如果表達式作為一個獨立語句段出現(xiàn)(參見 §2.4.6)(這只能是一個函數(shù)調(diào)用),它們的返回列表將被對齊到零個元素,也就是忽略所有返回值。如果表達式用于表達式列表的最后(或者是唯一)的元素,就不會有任何的對齊操作(除非函數(shù)調(diào)用用括號括起來)。在任何其它的情況下,Lua 將把表達式結(jié)果看成單一
35、元素,忽略除第一個之外的任何值。 這里有一些例子: f() - 調(diào)整到 0 個結(jié)果 g(f(), x) - f() 被調(diào)整到一個結(jié)果 g(x, f() - g 被傳入 x 加上所有 f() 的返回值 a,b,c = f(), x - f() 被調(diào)整到一個結(jié)果 ( c 在這里被賦為 nil ) a,b = . - a 被賦值為可變參數(shù)中的第一個, - b 被賦值為第二個 (如果可變參數(shù)中并沒有對應的值,- 這里 a 和 b 都有可能被賦為 nil) a,b,c = x, f() - f() 被調(diào)整為兩個結(jié)果 a,b,c = f() - f() 被調(diào)整為三個結(jié)果 return f() - 返回 f
36、() 返回的所有結(jié)果 return . - 返回所有從可變參數(shù)中接收來的值 return x,y,f() - 返回 x, y, 以及所有 f() 的返回值 f() - 用 f() 的所有返回值創(chuàng)建一個列表 . - 用可變參數(shù)中的所有值創(chuàng)建一個列表 f(), nil - f() 被調(diào)整為一個結(jié)果被括號括起來的表達式永遠被當作一個值。所以, (f(x,y,z) 即使 f 返回多個值,這個表達式永遠是一個單一值。((f(x,y,z) 的值是 f 返回的第一個值。如果 f 不返回值的話,那么它的值就是 nil 。) 2.5.1 - 數(shù)學運算操作符Lua 支持常見的數(shù)學運算操作符:二元操作 + (加法)
37、, - (減法),* (乘法), / (除法), % (取模),以及 (冪);和一元操作 - (取負)。如果對數(shù)字操作,或是可以轉(zhuǎn)換為數(shù)字的字符串(參見 §2.2.1),所有這些操作都依賴它通常的含義。冪操作可以對任何冪值都正常工作。比如, x(-0.5) 將計算出 x 平方根的倒數(shù)。取模操作被定義為 a % b = a - math.floor(a/b)*b這就是說,其結(jié)果是商相對負無窮圓整后的余數(shù)。(譯注:負數(shù)對正數(shù)取模的結(jié)果為正數(shù)) 2.5.2 - 比較操作符Lua 中的比較操作符有 = = < > <= >=這些操作的結(jié)果不是 false 就是 tru
38、e。 等于操作 (=) 首先比較操作數(shù)的類型。如果類型不同,結(jié)果就是 false。否則,繼續(xù)比較值。數(shù)字和字符串都用常規(guī)的方式比較。對象 (table ,userdata ,thread ,以及函數(shù))以引用的形式比較:兩個對象只有在它們指向同一個東西時才認為相等。每次你創(chuàng)建一個新對象(一個 table 或是 userdata ,thread 函數(shù)),它們都各不相同,即不同于上次創(chuàng)建的東西。 你可以改變 Lua 比較 table 和 userdata 的方式,這需要使用 "eq" 這個原方法(參見 §2.8)。 §2.2.1 中提及的轉(zhuǎn)換規(guī)則并不作用于比較
39、操作。所以, "0"=0 等于 false,而且 t0 和 t"0" 描述的是 table 中不同的域。 操作符 = 完全等價于 (=) 操作的反值。 大小比較操作以以下方式進行。如果參數(shù)都是數(shù)字,那么就直接做數(shù)字比較。否則,如果參數(shù)都是字符串,就用字符串比較的方式進行。再則,Lua 就試著調(diào)用 "lt" 或是 "le" 元方法(參見 §2.8)。 2.5.3 - 邏輯操作符Lua 中的邏輯操作符有 and, or, 以及 not。和控制結(jié)構(gòu)(參見 §2.4.4)一樣,所有的邏輯操作符把 fal
40、se 和 nil 都作為假,而其它的一切都當作真。 取反操作 not 總是返回 false 或 true 中的一個。與操作符 and 在第一個參數(shù)為 false 或 nil 時返回這第一個參數(shù);否則,and 返回第二個參數(shù)。或操作符 or 在第一個參數(shù)不為 nil 也不為 false 時,返回這第一個參數(shù),否則返回第二個參數(shù)。 and 和 or 都遵循短路規(guī)則;也就是說,第二個操作數(shù)只在需要的時候去求值。這里有一些例子: 10 or 20 -> 10 10 or error() -> 10 nil or "a" -> "a" nil a
41、nd 10 -> nil false and error() -> false false and nil -> false false or nil -> nil 10 and 20 -> 20(在這本手冊中, -> 指前面表達式的結(jié)果。) 2.5.4 - 連接符Lua 中字符串的連接操作符寫作兩個點 ('.')。如果兩個操作數(shù)都是字符串或都是數(shù)字,連接操作將以 §2.2.1 中提到的規(guī)則把其轉(zhuǎn)換為字符串。否則,會取調(diào)用元方法 "concat" (參見 §2.8)。 2.5.5 - 取長度操作符取長度
42、操作符寫作一元操作 #。字符串的長度是它的字節(jié)數(shù)(就是以一個字符一個字節(jié)計算的字符串長度)。 table t 的長度被定義成一個整數(shù)下標 n 。它滿足 tn 不是 nil 而 tn+1 為 nil;此外,如果 t1 為 nil ,n 就可能是零。對于常規(guī)的數(shù)組,里面從 1 到 n 放著一些非空的值的時候,它的長度就精確的為 n,即最后一個值的下標。如果數(shù)組有一個“空洞” (就是說,nil 值被夾在非空值之間),那么 #t 可能是指向任何一個是 nil 值的前一個位置的下標(就是說,任何一個 nil 值都有可能被當成數(shù)組的結(jié)束)。 2.5.6 - 優(yōu)先級Lua 中操作符的優(yōu)先級寫在下表中,從低到
43、高優(yōu)先級排序: or and < > <= >= = = . + - * / % not # - (unary) 通常,你可以用括號來改變運算次序。連接操作符 ('.') 和冪操作 ('') 是從右至左的。其它所有的操作都是從左至右。 2.5.7 - Table 構(gòu)造table 構(gòu)造子是一個構(gòu)造 table 的表達式。每次構(gòu)造子被執(zhí)行,都會構(gòu)造出一個新的 table 。構(gòu)造子可以被用來構(gòu)造一個空的 table,也可以用來構(gòu)造一個 table 并初始化其中的一些域。一般的構(gòu)造子的語法如下 tableconstructor := ´
44、 fieldlist ´fieldlist := field fieldsep field fieldsepfield := ´ exp ´ =´ exp | Name =´ exp | expfieldsep := ,´ | ;´每個形如 exp1 = exp2 的域向 table 中增加新的一項,其鍵值為 exp1 而值為 exp2。形如 name = exp 的域等價于 "name" = exp。最后,形如 exp 的域等價于 i = exp , 這里的 i 是一個從 1 開始不斷增長的數(shù)字。這這個
45、格式中的其它域不會破壞其記數(shù)。舉個例子: a = f(1) = g; "x", "y" x = 1, f(x), 30 = 23; 45 等價于 do local t = tf(1) = g t1 = "x" - 1st exp t2 = "y" - 2nd exp t.x = 1 - t"x" = 1 t3 = f(x) - 3rd exp t30 = 23 t4 = 45 - 4th exp a = t end如果表單中最后一個域的形式是 exp ,而且其表達式是一個函數(shù)調(diào)用或者是一個可變參
46、數(shù),那么這個表達式所有的返回值將連續(xù)的進入列表(參見 §2.5.8)。為了避免這一點,你可以用括號把函數(shù)調(diào)用(或是可變參數(shù))括起來(參見 §2.5)。 初始化域表可以在最后多一個分割符,這樣設計可以方便由機器生成代碼。 2.5.8 - 函數(shù)調(diào)用Lua 中的函數(shù)調(diào)用的語法如下: functioncall := prefixexp args函數(shù)調(diào)用時,第一步,prefixexp 和 args 先被求值。如果 prefixexp 的值的類型是 function,那么這個函數(shù)就被用給出的參數(shù)調(diào)用。否則 prefixexp 的元方法 "call" 就被調(diào)用,第一個
47、參數(shù)就是 prefixexp 的值,跟下來的是原來的調(diào)用參數(shù)(參見 §2.8)。 這樣的形式 functioncall := prefixexp :´ Name args可以用來調(diào)用 "方法"。這是 Lua 支持的一種語法糖。像 v:name(args) 這個樣子,被解釋成 (v,args),這里 v 只會被求值一次。 參數(shù)的語法如下: args := (´ explist1 )´args := tableconstructorargs := String所有參數(shù)的表達式求值都在函數(shù)調(diào)用之前。這樣的調(diào)用形式 ffields
48、 是一種語法糖用于表示 f(fields);這里指參數(shù)列表是一個單一的新創(chuàng)建出來的列表。而這樣的形式 f'string' (或是 f"string" 亦或是 fstring)也是一種語法糖,用于表示 f('string');這里指參數(shù)列表是一個單獨的字符串。 因為表達式語法在 Lua 中比較自由,所以你不能在函數(shù)調(diào)用的 '(' 前換行。這個限制可以避免語言中的一些歧義。比如你這樣寫 a = f (g).x(a)Lua 將把它當作一個單一語句段, a = f(g).x(a) 。因此,如果你真的想作為成兩個語句段,你必須在它們之間
49、寫上一個分號。如果你真的想調(diào)用 f,你必須從 (g) 前移去換行。 這樣一種調(diào)用形式:return functioncall 將觸發(fā)一個尾調(diào)用。 Lua 實現(xiàn)了適當?shù)奈膊空{(diào)用(或是適當?shù)奈策f歸):在尾調(diào)用中,被調(diào)用的函數(shù)重用調(diào)用它的函數(shù)的堆棧項。因此,對于程序執(zhí)行的嵌套尾調(diào)用的層數(shù)是沒有限制的。然而,尾調(diào)用將刪除調(diào)用它的函數(shù)的任何調(diào)試信息。注意,尾調(diào)用只發(fā)生在特定的語法下,這時, return 只有單一函數(shù)調(diào)用作為參數(shù);這種語法使得調(diào)用函數(shù)的結(jié)果可以精確返回。因此,下面這些例子都不是尾調(diào)用: return (f(x) - 返回值被調(diào)整為一個 return 2 * f(x) return x,
50、f(x) - 最加若干返回值 f(x); return - 無返回值 return x or f(x) - 返回值被調(diào)整為一個2.5.9 - 函數(shù)定義函數(shù)定義的語法如下: function := function funcbodyfuncbody := (´ parlist1 )´ block end另外定義了一些語法糖簡化函數(shù)定義的寫法: stat := function funcname funcbodystat := local function Name funcbodyfuncname := Name .´ Name :´ Name這樣的寫法:
51、 function f () body end被轉(zhuǎn)換成 f = function () body end這樣的寫法: function t.a.b.c.f () body end被轉(zhuǎn)換成 t.a.b.c.f = function () body end這樣的寫法: local function f () body end被轉(zhuǎn)換成 local f; f = function () body end注意,并不是轉(zhuǎn)換成 local f = function () body end(這個差別只在函數(shù)體內(nèi)需要引用 f 時才有。) 一個函數(shù)定義是一個可執(zhí)行的表達式,執(zhí)行結(jié)果是一個類型為 function
52、的值。當 Lua 預編譯一個 chunk 的時候, chunk 作為一個函數(shù),整個函數(shù)體也就被預編譯了。那么,無論何時 Lua 執(zhí)行了函數(shù)定義,這個函數(shù)本身就被實例化了(或者說是關閉了)。這個函數(shù)的實例(或者說是 closure(閉包)是表達式的最終值。相同函數(shù)的不同實例有可能引用不同的外部局部變量,也可能擁有不同的環(huán)境表。 形參(函數(shù)定義需要的參數(shù))是一些由實參(實際傳入?yún)?shù))的值初始化的局部變量: parlist1 := namelist ,´ .´ | .´當一個函數(shù)被調(diào)用,如果函數(shù)沒有被定義為接收不定長參數(shù),即在形參列表的末尾注明三個點 ('.
53、39;),那么實參列表就會被調(diào)整到形參列表的長度,變長參數(shù)函數(shù)不會調(diào)整實參列表;取而代之的是,它將把所有額外的參數(shù)放在一起通過變長參數(shù)表達式傳遞給函數(shù),其寫法依舊是三個點。這個表達式的值是一串實參值的列表,看起來就跟一個可以返回多個結(jié)果的函數(shù)一樣。如果一個變長參數(shù)表達式放在另一個表達式中使用,或是放在另一串表達式的中間,那么它的返回值就會被調(diào)整為單個值。若這個表達式放在了一系列表達式的最后一個,就不會做調(diào)整了(除非用括號給括了起來)。 我們先做如下定義,然后再來看一個例子: function f(a, b) end function g(a, b, .) end function r() re
54、turn 1,2,3 end下面看看實參到形參數(shù)以及可變長參數(shù)的映射關系: 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結(jié)果由 return 來返回(參見
55、167;2.4.4)。如果執(zhí)行到函數(shù)末尾依舊沒有遇到任何 return 語句,函數(shù)就不會返回任何結(jié)果。 冒號語法可以用來定義方法,就是說,函數(shù)可以有一個隱式的形參 self。因此,如下寫法: function t.a.b.c:f (params) body end是這樣一種寫法的語法糖: t.a.b.c.f = function (self, params) body end2.6 - 可視規(guī)則Lua 是一個有詞法作用范圍的語言。變量的作用范圍開始于聲明它們之后的第一個語句段,結(jié)束于包含這個聲明的最內(nèi)層語句塊的結(jié)束點。看下面這些例子: x = 10 - 全局變量 do - 新的語句塊 local x = x - 新的一個 'x', 它的值現(xiàn)在是 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 x = x 這樣的聲明,新的 x 正在
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 風險管理與評估試題及答案
- 《世界古代建筑欣賞:大二藝術史教學教案》
- 《太陽系八大行星的特點:四年級地理教學教案》
- 新員工入職流程及操作系統(tǒng)使用指南
- 產(chǎn)品分銷與代理業(yè)務合作協(xié)議內(nèi)容
- 《走進物理世界:高一物理實驗課程教案》
- 鄉(xiāng)村旅游農(nóng)業(yè)開發(fā)方案
- 年度市場活動策劃與執(zhí)行報告
- 公司采購協(xié)議附件書
- 采購居間合同例文
- 廣東省廣州市各縣區(qū)鄉(xiāng)鎮(zhèn)行政村村莊村名明細及行政區(qū)劃代碼
- 小學數(shù)學北師大二年級下冊六認識圖形認識角的導學單
- 綠化移植施工方案及技術措施
- 《竹枝詞》-完整版PPT
- 貴州區(qū)域地質(zhì)地史概述
- Aptitude態(tài)度的重要性
- 《推薦》500kV輸電線路應急處置預案6個
- 麗聲北極星分級繪本第三級下 The Class Trip 課件
- 第一課想聽聽我的忠告嗎
- 高英Lesson3 Pub Talk and the King27s English
- 《平方差公式(1)》導學案
評論
0/150
提交評論