版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、lua 5.0 參考手冊(cè) 作者: roberto ierusalimschy, luiz henrique de figueiredo, waldemar celes copyright 2003 tecgraf, puc-rio. all rights reserved. 譯者:shiningray nicholas nirvanastudio 1 - 緒論lua是一種為支持有數(shù)據(jù)描述機(jī)制的一般過(guò)程式編程語(yǔ)言而設(shè)計(jì)的擴(kuò)展編程語(yǔ)言。它同樣可以對(duì)面向?qū)ο笳Z(yǔ)言、函數(shù)式程序設(shè)計(jì)(functional programming,如lisp)以及數(shù)據(jù)驅(qū)動(dòng)編程(data-driven programming
2、)提供很好的支持。它的目標(biāo)是被用作一種強(qiáng)大的、輕型的配置語(yǔ)言。lua目前已經(jīng)被實(shí)現(xiàn)為一個(gè)擴(kuò)展庫(kù),是用clean c (ansi c/c+的一個(gè)通用子集)編寫(xiě)的。 作為一個(gè)擴(kuò)展語(yǔ)言,lua沒(méi)有main函數(shù)的概念:它僅僅是嵌入一個(gè)宿主程序進(jìn)行工作,可以稱之為 嵌入式編程 或者簡(jiǎn)單的說(shuō)是 宿主編程。這個(gè)宿主程序可以調(diào)用函數(shù)來(lái)執(zhí)行l(wèi)ua的代碼片斷,可以設(shè)置和讀取lua的變量,可以注冊(cè)c函數(shù)讓lua代碼調(diào)用。lua的能力可以擴(kuò)展到更大范圍,在不同的領(lǐng)域內(nèi),這樣就在同樣的語(yǔ)法框架下創(chuàng)建了你自定義的編程語(yǔ)言。 lua的發(fā)行版包括一個(gè)獨(dú)立的嵌入式程序,lua,他使用lua的擴(kuò)展庫(kù)來(lái)提供一個(gè)完全的lua解釋器。
3、 lua是自由軟件,通常不提供任何擔(dān)保,如它的版權(quán)說(shuō)明中敘述的那樣。 手冊(cè)中描述的實(shí)現(xiàn)在lua的官方網(wǎng)站可以找到,。 如果需要知道lua設(shè)計(jì)背后的一些決定和討論,可以參考以下論文,它們都可以在lua的網(wǎng)站上找到。 r.ierusalimschy, l.h.de figueiredo, and w.celes. lua-an extensible extension language. software: practice & experience 26 #6 (1996) 635-652. l.h.de figueiredo, r.ierusalimschy, and w
4、.celes. the design and implementation of a language for extending applications. proceedings of xxi brazilian seminar on software and hardware (1994) 273-283. l.h.de figueiredo, r.ierusalimschy, and w.celes. lua: an extensible embedded language. dr. dobbs journal 21 #12 (dec 1996) 26-33. r.ierusalims
5、chy, l.h.de figueiredo, and w.celes. the evolution of an extension language: a history of lua, proceedings of v brazilian symposium on programming languages (2001) b-14-b-28. lua在葡萄牙語(yǔ)中的意思是“月亮”,發(fā)音是 loo-ah。 2 - 語(yǔ)言這一章將描述lua的詞法、語(yǔ)法和語(yǔ)義結(jié)構(gòu)。換句話說(shuō),這一章會(huì)講什么標(biāo)記是合法的,他們是如何組合的,以及他們的組合是什么含義。 語(yǔ)言結(jié)構(gòu)會(huì)使用常用的擴(kuò)展bnf范式來(lái)解釋,如a表示0
6、或多個(gè)a, a表示a是可選的(0個(gè)或1個(gè))。非終端字體(不能顯示的)用 斜體表示,關(guān)鍵字是粗體,其他終端符號(hào)用typewriter(等寬)字體,并用單引號(hào)引出。 2.1 - 詞法約定lua中的標(biāo)識(shí)符(identifiers)可以是任意的數(shù)字、字符和下劃線“_”,但不能以數(shù)字開(kāi)頭。這條規(guī)則符合大多數(shù)編程語(yǔ)言中的標(biāo)識(shí)符的定義。(字符的具體定義要根據(jù)系統(tǒng)的地區(qū)設(shè)置:任何區(qū)域設(shè)置可以認(rèn)同的字母表中的字母都可以用在標(biāo)識(shí)符中。) 下面的關(guān)鍵字(keywords)為保留關(guān)鍵字不可以作為標(biāo)識(shí)符出現(xiàn): and break do else elseif end false for function if in l
7、ocal nil not or repeat return then true until whilelua對(duì)大小寫(xiě)敏感:and是一個(gè)保留字,但是 and 和 and 是兩個(gè)不一樣的、但都合法的標(biāo)識(shí)符。習(xí)慣上來(lái)說(shuō),以下劃線開(kāi)始且后面跟著大寫(xiě)字母的標(biāo)識(shí)符 (例如 _version) 是為lua內(nèi)部變量所保留的。 下面的字符(串)是其他的一些標(biāo)記: + - * / = = = = ( ) ; : , . . .字符串(literal strings) 以單引號(hào)或者雙引號(hào)定界,同時(shí)可以包含以下c語(yǔ)言風(fēng)格的轉(zhuǎn)義字符: a - 鈴聲(bell) b - 回退(backspace) f - form fe
8、ed n - 新行(newline) r - 回車(carriage return) t - 水平制表符(horizontal tab) v - 垂直制表符(vertical tab) - 反斜杠(backslash) - 雙引號(hào)(quotation mark) - 單引號(hào)(apostrophe) - 左方括號(hào)(left square bracket) - 右方括號(hào)(right square bracket) 另外,一個(gè) newline (一個(gè)反斜杠加上一個(gè)真正的換行符)會(huì)導(dǎo)致字符串內(nèi)的分行。字符串中的字符也可以使用轉(zhuǎn)義字符ddd通過(guò)數(shù)字值來(lái)指定。ddd 是最多為3個(gè)十進(jìn)制數(shù)字的序列。lua中
9、的字符串也可以包含8進(jìn)制數(shù)字,包括嵌入零,它可以表示為 0。 字符串也可以用雙方括號(hào)來(lái)定界 。這種括號(hào)方式的語(yǔ)法,字符串可以跨越多行,也可以包含嵌套的,同時(shí)不會(huì)轉(zhuǎn)義任何序列。方便起見(jiàn),當(dāng)開(kāi)始的 后面緊跟著一個(gè)換行符的話,這個(gè)換行符不會(huì)包括在字符串內(nèi)。舉個(gè)例子:在一個(gè)使用ascii編碼(其中a 的編碼是97,換行符是10,字符1 是49)的系統(tǒng)中,以下四種格式得到的都是同一個(gè)字符串: (1) alon123 (2) 97lo1004923 (3) alo 123 (4) alo 123數(shù)值常量(numerical constants) 可以有一個(gè)可選的底數(shù)部分和一個(gè)可選的指數(shù)部分。以下是有效的數(shù)
10、值常量: 3 3.0 3.1416 314.16e-2 0.31416e1注釋(comments) 可以在任何地方出現(xiàn),必須在最前面加上雙減號(hào) (-)。如果緊接著 - 的文本不是 ,那么會(huì)認(rèn)為是一個(gè) 短注釋(short comment), 這一行往后到行尾都是注釋。否則,會(huì)認(rèn)為是一個(gè) 常注釋(long comment),注釋直到相應(yīng)的 結(jié)束。長(zhǎng)注釋可以跨越多行,同時(shí)可以包含嵌套的 括號(hào)對(duì)。 為了方便起見(jiàn),文件的第一行如果是以#開(kāi)始,這個(gè)機(jī)制允許lua在unix系統(tǒng)中用做一個(gè)腳本解釋器(見(jiàn) 6)。2.2 - 值和類型lua是一種 動(dòng)態(tài)類型語(yǔ)言(dynamically typed language
11、)。這意味著變量是沒(méi)有類型的;只有值才有。語(yǔ)言中沒(méi)有類型定義。所有的值都包含他自身的類型。lua中有八種基本類型:nil, boolean, number, string, function, userdata, thread 和 table。 nil 空類型只對(duì)應(yīng) nil值,他的屬性和其他任何值都有區(qū)別;通常它代表沒(méi)有有效的值。 boolean 布爾類型有兩種不同的值 false and true。在lua中, nil and false 代表成假條件;其他任何值都代表成真條件。 number 數(shù)字類型表示實(shí)數(shù)(雙精度浮點(diǎn)數(shù))。(構(gòu)建lua解釋器時(shí)也可以很容易地用其他內(nèi)部的表示方式表示數(shù)字,
12、如單精度浮點(diǎn)數(shù)或者長(zhǎng)整型)。 string 字符串類型表示一個(gè)字符的序列。lua 字符串可以包含8位字符,包括嵌入的 (0) (見(jiàn) 2.1)。 函數(shù)是lua中的 第一類值(first-class values)。也就是說(shuō)函數(shù)可以保存在變量中,當(dāng)作參數(shù)傳遞給其他函數(shù),或者被當(dāng)作結(jié)果返回。lua可以調(diào)用(和處理)lua寫(xiě)的函數(shù)和c寫(xiě)的函數(shù) (見(jiàn) 2.5.7)。 用戶數(shù)據(jù)類型(userdata) 提供了讓任意c數(shù)據(jù)儲(chǔ)存在lua變量中的功能。這種類型直接對(duì)應(yīng)著一塊內(nèi)存,lua中也沒(méi)有任何預(yù)先定義的操作,除了賦值和一致性比較。然而,通過(guò)使用 元表(metatables),程序員可以定義處理userdat
13、a的操作。(見(jiàn) 2.8)。 userdata 值不能在lua中建立或者修改,只能通過(guò) capi。這保證了宿主程序的數(shù)據(jù)完整性。 線程(thread) 類型代表了相互獨(dú)立的執(zhí)行線程,用來(lái)實(shí)現(xiàn)同步程序。 表(table) 類型實(shí)現(xiàn)了聯(lián)合數(shù)組,也就是說(shuō),數(shù)組不僅可以使用數(shù)字,還能使用其他的值(除了 nil)。 而且,tables 可以是 互異的(heterogeneous),他們可以保存任何類型的值(除了 nil)。 tables 是lua中唯一的數(shù)據(jù)結(jié)構(gòu)機(jī)制;他們可以用來(lái)表示一般數(shù)組,特征表,集合,記錄,圖,樹(shù)等等。如果要表示記錄,lua使用字段名作為索引。語(yǔ)言支持 這種比較優(yōu)美的表
14、示方式,還有 aname。在lua中有幾種建立表的簡(jiǎn)便方法 (見(jiàn) 2.5.6)。 就像索引一樣,表字段的值也可以是任何類型(除了 nil)。特別需要注意地是,由于函數(shù)是第一型的值,表字段也可以包含函數(shù)。這樣表也可以支持 方法(methods) (見(jiàn) 2.5.8)。 表,函數(shù),和用戶數(shù)據(jù)類型的值都是 對(duì)象(objects):變量不會(huì)包含他們的實(shí)際值,只是一個(gè)他們的引用(references)。 賦值,參數(shù)傳遞和函數(shù)返回只是操作這些值的引用,這些操作不會(huì)暗含任何拷貝。 庫(kù)函數(shù) type 返回一個(gè)字符串描述給出值所表示的類型 (見(jiàn) 5.1)。 2.2.1 - 類型轉(zhuǎn)換lua提供運(yùn)行時(shí)的數(shù)字和字符串值
15、得自動(dòng)轉(zhuǎn)換。任何對(duì)字符串的算術(shù)操作都會(huì)現(xiàn)嘗試把字符串轉(zhuǎn)換成數(shù)字,使用一般規(guī)則轉(zhuǎn)換。反過(guò)來(lái),當(dāng)一個(gè)數(shù)值用在需要字符串的地方時(shí),數(shù)字會(huì)自動(dòng)轉(zhuǎn)換成字符串,遵循一種合理的格式。如果要指定數(shù)值如何轉(zhuǎn)換成字符串,請(qǐng)使用字符串庫(kù)中的 format 函數(shù)(見(jiàn) 5.3)。2.3 - 變量變量是儲(chǔ)存值的地方。lua中有三種不同的變量:全局變量,局部變量和表字段。 一個(gè)名稱可以表示全局變量或局部變量(或者一個(gè)函數(shù)的正式參數(shù),一種局部變量的特殊形式): var := namelua假設(shè)變量是全局變量,除非明確地用local進(jìn)行聲明 (見(jiàn) 2.4.7)。局部變量有 詞義范圍(lexically scoped):局部變量
16、可以被在它們范圍內(nèi)的函數(shù)自由訪問(wèn) (見(jiàn) 2.6)。 在變量第一次賦值之前,它的值是 nil。 方括號(hào)用于對(duì)表進(jìn)行檢索: var := prefixexp exp 第一個(gè)表達(dá)式 (prefixexp)結(jié)果必須是表;第二個(gè)表達(dá)式 (exp) 識(shí)別表中一個(gè)特定條目。給出表的表達(dá)式有一個(gè)限制語(yǔ)法;詳細(xì)見(jiàn) 2.5。 var.name 語(yǔ)法是 varname 的較好形式: var := prefixexp . name訪問(wèn)全局變量和表字段的實(shí)質(zhì)可以通過(guò)元表進(jìn)行改變。對(duì)索引變量 ti 的訪問(wèn)等同于調(diào)用 gettable_event(t,i)。(關(guān)于 gettable_event 的完整描述見(jiàn) 2.8。這個(gè)函
17、數(shù)并沒(méi)有在lua中定義,也無(wú)法調(diào)用。我們?cè)谶@里僅僅用來(lái)解釋原理)。 所有的全局變量存在一個(gè)普通的lua表中,稱之為 環(huán)境變量表(environment tables) 或簡(jiǎn)稱 環(huán)境(environments)。由c寫(xiě)的并導(dǎo)入到lua中的函數(shù) (c 函數(shù)) 全部共享一個(gè)通用 全局環(huán)境(global environment)。lua寫(xiě)的每個(gè)函數(shù) (a lua 函數(shù)) 都有一個(gè)它自己的環(huán)境的引用,這樣這個(gè)函數(shù)中的所有的全局變量都會(huì)指向這個(gè)環(huán)境變量表。當(dāng)新創(chuàng)建一個(gè)函數(shù)時(shí),它會(huì)繼承創(chuàng)建它的函數(shù)的環(huán)境。要改變或者獲得lua函數(shù)的環(huán)境表,可以調(diào)用 setfenv or getfenv (見(jiàn) 5.1)。 訪問(wèn)
18、全局變量 x 等同于 _env.x,又等同于 gettable_event(_env, x)_env 是運(yùn)行的函數(shù)的環(huán)境。(_env 變量并沒(méi)有在lua中定義。我們這里僅僅用來(lái)解釋原理) 2.4 - 語(yǔ)句lua支持一種很通俗的語(yǔ)句集,和pascal或者c中的很相似。他包括賦值,控制結(jié)構(gòu),過(guò)程調(diào)用,表構(gòu)造和變量聲明。 2.4.1 - 語(yǔ)句段lua執(zhí)行的最小單元稱之為一個(gè) 段(chunk)。一段語(yǔ)句就是簡(jiǎn)單的語(yǔ)句的序列,以順序執(zhí)行。每一個(gè)語(yǔ)句后面都可以加上一個(gè)分號(hào)(可選): chunk := stat ;lua將語(yǔ)句段作為一個(gè)匿名函數(shù) (見(jiàn) 2.5.8) 的本體進(jìn)行處理。這樣,語(yǔ)句段可以定義局部變
19、量或者返回值。 一段語(yǔ)句可以儲(chǔ)存在文件內(nèi)或者宿主程序的一個(gè)字符串中。當(dāng)語(yǔ)句段被執(zhí)行時(shí),他首先被預(yù)編譯成虛擬機(jī)使用的字節(jié)碼,然后虛擬機(jī)用一個(gè)解釋器執(zhí)行被編譯的代碼。 語(yǔ)句段也可以被預(yù)編譯為二進(jìn)制代碼;詳情參看 luac 程序。源代碼和編譯形態(tài)可以互相轉(zhuǎn)換;lua自動(dòng)監(jiān)測(cè)文件類型然后作相應(yīng)操作。 2.4.2 - 語(yǔ)句塊一個(gè)語(yǔ)句塊是一系列語(yǔ)句;從語(yǔ)句構(gòu)成上來(lái)看,語(yǔ)句塊等同于語(yǔ)句段:block := chunk一個(gè)語(yǔ)句塊可以明確定界來(lái)替換單個(gè)語(yǔ)句:stat := do block end顯式語(yǔ)句塊可以很好地控制變量的聲明范圍。顯示語(yǔ)句塊有時(shí)也常會(huì)在另一個(gè)語(yǔ)句塊的中間添加 return 或 break
20、語(yǔ)句 (見(jiàn) 2.4.4)。 2.4.3 - 賦值lua允許多重賦值。因此,賦值的語(yǔ)法定義為:等號(hào)左邊是一個(gè)變量表,右邊是一個(gè)表達(dá)式表。兩邊的表中的元素都用逗號(hào)分隔開(kāi)來(lái):stat := varlist1 = explist1varlist1 := var , varexplist1 := exp , exp我們將在 2.5 討論表達(dá)式。 在賦值之前,值的表長(zhǎng)度會(huì)被 調(diào)整 為和變量的表一樣。如果值比需要的多,多出的值就會(huì)被扔掉。如果值的數(shù)量不夠,就會(huì)用足夠多的 nil 來(lái)填充表直到滿足數(shù)量要求。如果表達(dá)式表以一個(gè)函數(shù)調(diào)用結(jié)束,那么在賦值之前,函數(shù)返回的所有的值都會(huì)添加到值的表中(除非把函數(shù)調(diào)用放在
21、括號(hào)里面;見(jiàn) 2.5)。 賦值語(yǔ)句首先計(jì)算出所有的表達(dá)式,然后才會(huì)執(zhí)行賦值,所以代碼: i = 3 i, ai = i+1, 20設(shè)置 a3 為 20,但不影響 a4。因?yàn)樵?ai 中的 i 在賦值為4之前是等于3。同樣的,下面這行: x, y = y, x可以交換 x 和 y 的值。 對(duì)全局變量和表字段的賦值可以看作是通過(guò)元表進(jìn)行的。對(duì)一個(gè)索引變量的賦值 ti = val 等同于 settable_event(t,i,val)。 (settable_event詳細(xì)介紹參看 2.8 ,lua中并未定義該函數(shù),他也無(wú)法直接調(diào)用。我們這里只是用它來(lái)進(jìn)行解釋。) 對(duì)全局變量的賦值 x = val 等
22、同于賦值語(yǔ)句 _env.x = val,像前面也等同于: settable_event(_env, x, val)_env 是運(yùn)行函數(shù)的環(huán)境。(_env 變量并未在lua中定義。我們這里只是用來(lái)進(jìn)行解釋。) 2.4.4 - 控制結(jié)構(gòu)控制結(jié)構(gòu) if, while 和 repeat 具有通用的含義和類似的語(yǔ)法: stat := while exp do block endstat := repeat block until expstat := if exp then block elseif exp then block else block endlua也有 for 語(yǔ)句,有兩種格式 (見(jiàn) 2
23、.4.5)。 控制結(jié)構(gòu)的條件表達(dá)式 exp 可以返回任意值。false 和 nil 都表示假。所有其他的值都認(rèn)為是真(特別要說(shuō)明的:數(shù)字0和空字符串也表示真)。 語(yǔ)句 return 用來(lái)從函數(shù)或者是語(yǔ)句段中返回一個(gè)值。函數(shù)和語(yǔ)句段都可以返回多個(gè)值,所以 return 語(yǔ)句的語(yǔ)法為:stat := return explist1break 語(yǔ)句可以用來(lái)終止while, repeat 或者 for 循環(huán)的執(zhí)行,直接跳到循環(huán)后面的語(yǔ)句。 stat := breakbreak 結(jié)束最里面的一個(gè)循環(huán)。 由于語(yǔ)法的原因, return 和 break 語(yǔ)句只能作為語(yǔ)句塊的 最后一個(gè) 語(yǔ)句。如果確實(shí)需要在語(yǔ)
24、句塊的中間使用 return 或者 break,需要使用一個(gè)顯示語(yǔ)句塊: do return end 和 do break end,這樣現(xiàn)在 return 和 break 就成為他們(內(nèi)部)語(yǔ)句塊中的最后一個(gè)語(yǔ)句了。實(shí)際上,這兩種用法一般只用在調(diào)試中。 2.4.5 - for 語(yǔ)句for 語(yǔ)句有兩種形式:數(shù)值形式和一般形式。 數(shù)值形式的 for 循環(huán)根據(jù)一個(gè)控制變量用算術(shù)過(guò)程重?匆揮錁?shù)繖邃u縵攏? stat := for name = exp , exp , exp do block endblock 語(yǔ)句塊根據(jù) name 以第一個(gè) exp 的值開(kāi)始,直到他以第三個(gè) exp 為步長(zhǎng)達(dá)到了第二個(gè)
25、 exp。一個(gè)這樣的 for 語(yǔ)句: for var = e1, e2, e3 do block end等價(jià)于一下代碼: do local var, _limit, _step = tonumber(e1), tonumber(e2), tonumber(e3) if not (var and _limit and _step) then error() end while (_step0 and var=_limit) or (_step=_limit) do block var = var + _step end end注意: 三種控制表達(dá)式只會(huì)被計(jì)算一次,在循環(huán)開(kāi)始之前。他們的結(jié)果必須是
26、數(shù)值。 _limit 和 _step 是不可見(jiàn)的變量。這里只是為了進(jìn)行解釋。 如果你在程序塊內(nèi)給 var 賦值,結(jié)果行為將會(huì)不確定。 如果沒(méi)有給出第三個(gè)表達(dá)式(步長(zhǎng)),那么默認(rèn)為1。 你可以使用 break 來(lái)退出 for 循環(huán)。 循環(huán)變量 var 是局部變量;你不可以在 for 循環(huán)結(jié)束之后繼續(xù)使用。如果你需要使用這個(gè)值,請(qǐng)?jiān)谕顺鲅h(huán)之前把它們傳給其他變量。 for 的語(yǔ)句的一般形式是操作于函數(shù)之上的,稱之為迭代器(iterators)。每一個(gè)迭代過(guò)程,它調(diào)用迭代函數(shù)來(lái)產(chǎn)生新的值,直到新的值是 nil 。一般形式 for 循環(huán)有如下語(yǔ)法: stat := for name , name in
27、 explist1 do block end一個(gè)這樣的 for 語(yǔ)句 for var_1, ., var_n in explist do block end等同于以下代碼: do local _f, _s, var_1 = explist local var_2, . , var_n while true do var_1, ., var_n = _f(_s, var_1) if var_1 = nil then break end block end end注意: explist 只會(huì)計(jì)算一次。他的結(jié)果是一個(gè) 迭代 函數(shù),一個(gè) 狀態(tài),和給第一個(gè) 迭代變量的一個(gè)初始值。 _f 和 _s 是不可
28、見(jiàn)的變量。這里只是用來(lái)進(jìn)行解釋說(shuō)明。 如果你在語(yǔ)句塊中給 var_1 賦值,那么行為就會(huì)變得不確定。 你可以使用 break 來(lái)退出 for 循環(huán)。 循環(huán)變量 var_i 是局部變量;你不可以在 for 循環(huán)結(jié)束之后繼續(xù)使用。如果你需要使用這個(gè)值,請(qǐng)?jiān)谕顺鲅h(huán)之前把它們傳給其他變量。 2.4.6 - 語(yǔ)句式函數(shù)調(diào)用如果要忽略可能的影響,函數(shù)調(diào)用可以按照語(yǔ)句執(zhí)行: stat := functioncalli在這里,所有的返回值都會(huì)被忽略。函數(shù)調(diào)用將在 2.5.7 詳細(xì)解釋。 2.4.7 - 局部變量聲明局部變量可以在語(yǔ)句塊中任何地方聲明。聲明時(shí)也可以添加一個(gè)初始賦值: stat := local
29、 namelist = explist1namelist := name , name如果出現(xiàn)初始賦值,他的語(yǔ)法和多重賦值語(yǔ)句一樣(見(jiàn) 2.4.3)。否則,所有的變量都會(huì)初始化為 nil。 一個(gè)語(yǔ)句段也是一個(gè)語(yǔ)句塊(見(jiàn) 2.4.1),所以語(yǔ)句段之內(nèi)的任何顯式語(yǔ)句塊之外也可以聲明局部變量。這種局部變量在語(yǔ)句段結(jié)束就會(huì)銷毀。 局部變量的可見(jiàn)規(guī)則會(huì)在 2.6解釋。 2.5 - 表達(dá)式lua中有以下幾種基本表達(dá)式: exp := prefixexpexp := nil | false | trueexp := numberexp := literalexp := functionexp := tabl
30、econstructorprefixexp := var | functioncall | ( exp )數(shù)字和字符串已經(jīng)在 2.1 中解釋;變量在 2.3 中解釋;函數(shù)定義在 2.5.8;函數(shù)調(diào)用在 2.5.7;表構(gòu)造器在 2.5.6。 一個(gè)用括號(hào)括起的表達(dá)式只會(huì)返回一個(gè)值。這樣,(f(x,y,z) 將只會(huì)返回單一的一個(gè)值,即使 f 可以返回多個(gè)值,((f(x,y,z) 的值將是 f 返回的第一個(gè)值或者如果 f 沒(méi)有返回任何值就是 nil )。 表達(dá)式也可以使用各種算術(shù)運(yùn)算符,關(guān)系運(yùn)算符和邏輯運(yùn)算符,下面幾節(jié)就會(huì)講到。 2.5.1 - 算術(shù)運(yùn)算符lua支持常見(jiàn)的幾種運(yùn)算符:二元 + (加),
31、 - (減), * (乘), / (除), 以及 (指數(shù)運(yùn)算); 一元 - (負(fù)號(hào))。如果操作數(shù)是數(shù)字,或者是可以轉(zhuǎn)換成數(shù)字的字符串(見(jiàn) 2.2.1),那么所有的操作都和算術(shù)意義上的運(yùn)算一致(除了指數(shù))。指數(shù)運(yùn)算其實(shí)是調(diào)用一個(gè)全局函數(shù) _pow,否則一個(gè)合適的元方法將會(huì)被調(diào)用(見(jiàn) 2.8)。標(biāo)準(zhǔn)數(shù)學(xué)庫(kù)定義了函數(shù) _pow,給出了指數(shù)運(yùn)算的定義(見(jiàn) 5.5)。 2.5.2 - 關(guān)系運(yùn)算符lua中的關(guān)系運(yùn)算符有 = = =這些運(yùn)算只會(huì)產(chǎn)生 false 或 true值。 等于 (=) 先比較操作數(shù)的類型。如果類型不一樣,結(jié)果便是 false。否則,再比較操作數(shù)的值。對(duì)象(表,用戶數(shù)據(jù),線程,和函數(shù))
32、是按照引用進(jìn)行比較:只有兩個(gè)對(duì)象是同一個(gè)對(duì)象的時(shí)候,才認(rèn)為是相等。每次你創(chuàng)建一個(gè)新的對(duì)象(表,用戶數(shù)據(jù),或者是函數(shù))。這個(gè)新的對(duì)象將不同于前面存在的任何對(duì)象。 你可以用eq元方法改變lua比較表的方式(見(jiàn) 2.8)。 2.2.1 的轉(zhuǎn)換規(guī)則 不適用 于相等比較。這樣, 0=0 結(jié)果是 false ,同樣 t0 和 t0 給出的是表中不同的字段。 而操作符 = 是等于 (=) 的相反的操作。 t操作符的執(zhí)行順序如下。如果兩個(gè)參數(shù)都是數(shù)字,那么它們就直接進(jìn)行比較。如果,兩個(gè)參數(shù)都是字符串,那么它們的值會(huì)根據(jù)當(dāng)前的區(qū)域設(shè)置進(jìn)行比較。否則,lua嘗試調(diào)用lt或者 le 元方法(見(jiàn) 2.8)。 2.5.
33、3 - 邏輯運(yùn)算符lua中的邏輯運(yùn)算符是: and or not和控制結(jié)構(gòu)一樣(見(jiàn) 2.4.4),所有的邏輯操作符認(rèn)為 false 和 nil 都是假,其他的值都是真。 not 操作符總是返回 false 或 true。 合取運(yùn)算 and 如果第一個(gè)參數(shù)是 false 或者 nil 則返回第一個(gè)參數(shù);否則 and 返回第二個(gè)參數(shù)。析取運(yùn)算 or 如果第一個(gè)參數(shù)不是 nil 或 false 則返回第一個(gè)參數(shù),否則 or 返回第二個(gè)參數(shù)。 and 和 or 都使用截取計(jì)算,也就是,只有有必要的情況下才計(jì)算第二個(gè)參數(shù)。例如: 10 or error() - 10 nil or a - a nil a
34、nd 10 - nil false and error() - false false and nil - false false or nil - nil 10 and 20 - 202.5.4 - 串聯(lián)接在lua中字符串連接操作符是兩個(gè)點(diǎn) (.)。如果兩邊的操作數(shù)都是字符或者數(shù)字,他們就都會(huì)按照 2.2.1的規(guī)則被轉(zhuǎn)換成字符串。否則,將調(diào)用 concat 元方法(見(jiàn) 2.8)。 2.5.5 - 優(yōu)先級(jí)lua中的操作符的優(yōu)先級(jí)如下表所示,從低到高優(yōu)先級(jí): or and = = = . + - * / not - (unary) 表達(dá)式中,你可以使用括號(hào)來(lái)改變優(yōu)先順序。串聯(lián)接符 (.) ?橢甘
35、? () 都是右結(jié)合的。其他二元操作都是左結(jié)合的。 2.5.6 - 表構(gòu)造器表構(gòu)造器是創(chuàng)建表的表達(dá)式。當(dāng)計(jì)算構(gòu)造器的時(shí)候,就會(huì)創(chuàng)建一個(gè)新的表。構(gòu)造器可以用來(lái)創(chuàng)建空的表,或者創(chuàng)建表并初始化一些字段。一般的語(yǔ)法如下: tableconstructor := fieldlist fieldlist := field fieldsep field fieldsepfield := exp = exp | name = exp | expfieldsep := , | ;exp1 = exp2 形式的每一個(gè)添加到新表中的字段條目以 exp1 為鍵并以 exp2 為值。name = exp 形式的字段,等
36、同于 name = exp。最后,exp 形式的字段等同于 i = exp 其中 i 是連續(xù)的整數(shù),從1開(kāi)始。其它格式的字段不會(huì)影響它的計(jì)數(shù)。例如: a = f(1) = g; x, y; x = 1, f(x), 30 = 23; 45等同于: do local temp = tempf(1) = g temp1 = x - 1st exp temp2 = y - 2nd exp temp.x = 1 - tempx = 1 temp3 = f(x) - 3rd exp temp30 = 23 temp4 = 45 - 4th exp a = temp end如果列表中最后一個(gè)字段的形式是
37、exp 同時(shí)表達(dá)式又是一個(gè)函數(shù)調(diào)用,那么調(diào)用返回的所有值會(huì)依次進(jìn)入列表(見(jiàn) 2.5.7)。如果要避免這種情況,在函數(shù)調(diào)用兩邊加上括號(hào)(見(jiàn) 2.5)。 字段列表可以有一個(gè)結(jié)尾的分隔符,這個(gè)對(duì)由機(jī)器生成的列表十分方便。 2.5.7 - 函數(shù)調(diào)用lua中的一個(gè)函數(shù)調(diào)用有如下語(yǔ)法: functioncall := prefixexp args在函數(shù)調(diào)用中,首先會(huì)計(jì)算 prefixexp 和 args 。如果 prefixexp 的值是 function 類型,那么那個(gè)函數(shù)就會(huì)被調(diào)用,同時(shí)使用給出的參數(shù)。否則,他的 call 元方法就會(huì)被調(diào)用,第一個(gè)參數(shù)是 prefixexp 的值,接下來(lái)是原來(lái)的調(diào)用參
38、數(shù)(見(jiàn) 2.8)。 形式 functioncall := prefixexp : name args可以用來(lái)調(diào)用“方法”(methods)。調(diào)用 v:name(.) 語(yǔ)法上比 (v,.),要好一些,除非表達(dá)式 v 只計(jì)算一次。 參數(shù)可以有以下幾種語(yǔ)法: args := ( explist1 )args := tableconstructorargs := literal所有的參數(shù)表達(dá)式都會(huì)在實(shí)際調(diào)用之前進(jìn)行計(jì)算。f. 的調(diào)用形式在語(yǔ)法上較 f(.) 要好,是因?yàn)?,參?shù)列表示一個(gè)單獨(dú)的新表。 f. (或者 f. 或者 f.) 較 f(.) 要好,是因?yàn)閰?shù)列表是一個(gè)單獨(dú)的字符串。 因
39、為函數(shù)可以返回任意個(gè)結(jié)果(見(jiàn) 2.4.4),結(jié)果的數(shù)量必須在使用它們前進(jìn)行調(diào)整。如果函數(shù)按照語(yǔ)句進(jìn)行調(diào)用(見(jiàn) 2.4.6),那么它的返回列表就會(huì)被調(diào)整為零個(gè)元素,這樣就舍棄了所有的返回值。如果調(diào)用函數(shù)時(shí),他是一個(gè)表達(dá)式列表的最后一個(gè)元素,那么不會(huì)做調(diào)整(除非調(diào)用時(shí)加了括號(hào))。 以下是一些例子: f() - 調(diào)整為0個(gè)結(jié)果 g(f(), x) - f() 被調(diào)整成1個(gè)結(jié)果 g(x, f() - g 獲得 x 加上f()返回的所有值 a,b,c = f(), x - f() 被調(diào)整成1個(gè)結(jié)果(此時(shí)c獲得nil值) a,b,c = x, f() - f() 被調(diào)整為兩個(gè)結(jié)果 a,b,c = f()
40、- f() 被調(diào)整為3個(gè)結(jié)果 return f() - 返回所有 f() 返回的值 return x,y,f() - 建立一個(gè)表包含所有 f() 返回的值 f() - creates a list with all values returned by f() f(), nil - f() 被調(diào)整為一個(gè)結(jié)果如果你用括號(hào)括起調(diào)用的函數(shù),那么它就會(huì)被調(diào)整為返回一個(gè)值。 return x,y,(f() - returns x, y, and the first value from f() (f() - creates a table with exactly one element作為lua語(yǔ)法自
41、由格式的一個(gè)例外,你不能在函數(shù)調(diào)用的 ( 前面加入一個(gè)換行。這個(gè)限制可以避免語(yǔ)言中的一些二義性。如果你寫(xiě): a = f (g).x(a)lua會(huì)讀作 a = f(g).x(a)。這樣,如果你想執(zhí)行為兩條語(yǔ)句,你必須在中間加分號(hào)。如果你實(shí)際上想調(diào)用 f,你就必須刪除 (g) 前面的換行。 return functioncall 的調(diào)用格式稱之為 尾部調(diào)用(tail call)。lua實(shí)現(xiàn)了proper tail calls;在一個(gè)尾部調(diào)用中,被調(diào)用的函數(shù)將會(huì)重新使用調(diào)用程序的棧。因此,程序執(zhí)行對(duì)嵌套尾部調(diào)用的次數(shù)沒(méi)有任何限制。然而,尾部調(diào)用會(huì)清楚調(diào)用函數(shù)的調(diào)試信息。注意尾部調(diào)用只有在特殊的語(yǔ)法中
42、才能出現(xiàn),也就是 return 只有一個(gè)函數(shù)調(diào)用作為參數(shù),這種語(yǔ)法保證了調(diào)用函數(shù)確切返回被調(diào)用函數(shù)的返回值。所以,下面的例子都不是尾部調(diào)用: return (f(x) - results adjusted to 1 return 2 * f(x) return x, f(x) - additional results f(x); return - results discarded return x or f(x) - results adjusted to 12.5.8 - 函數(shù)定義函數(shù)定義的語(yǔ)法是: function := function funcbodyfuncbody := ( pa
43、rlist1 ) block end下面較好的語(yǔ)法簡(jiǎn)化了函數(shù)定義: stat := function funcname funcbodystat := local function name funcbodyfuncname := name . name : name語(yǔ)句 function f () . end會(huì)被翻譯為 f = function () . end語(yǔ)句 function t.a.b.c.f () . end會(huì)被翻譯為 t.a.b.c.f = function () . end語(yǔ)句 local function f () . end會(huì)被翻譯為 local f; f = funct
44、ion () . end一個(gè)函數(shù)定義是一個(gè)可執(zhí)行的表達(dá)式,他的類型為 函數(shù)(function) 。當(dāng)lua預(yù)編譯語(yǔ)句段的時(shí)候,他的函數(shù)體也會(huì)被預(yù)編譯。這樣,當(dāng)lua執(zhí)行函數(shù)定義的時(shí)候,函數(shù)被 實(shí)例化 (封裝 closed)。這個(gè)函數(shù)實(shí)例(或閉包 closure)是表達(dá)式的最終結(jié)果。同一個(gè)函數(shù)的不同的實(shí)例可以引用不同的外部局部變量也可以有不同的環(huán)境表。 形式參數(shù)(代表參數(shù)的變量,簡(jiǎn)稱形參)就像用實(shí)際參數(shù)值(簡(jiǎn)稱實(shí)參)初始化的局部變量一樣。 parlist1 := namelist , .parlist1 := .當(dāng)調(diào)用一個(gè)函數(shù)時(shí),實(shí)參表會(huì)調(diào)整為和形參一樣的長(zhǎng)度,除非函數(shù)是 variadic 或者
45、 變長(zhǎng)參數(shù)函數(shù)(vararg function)。變長(zhǎng)參數(shù)函數(shù)在其參數(shù)列表最后有三個(gè)點(diǎn) (.)。 變長(zhǎng)參數(shù)函數(shù)不會(huì)對(duì)參數(shù)列表進(jìn)行調(diào)整;而是,它把所有的額外實(shí)參放到一個(gè)隱含的形參 arg中。 arg 的值是一個(gè)表,包含一個(gè)字段n 表示額外參數(shù)的個(gè)數(shù),位置 1,2,.,n是額外的參數(shù)。 請(qǐng)思考以下函數(shù)定義的例子: function f(a, b) end function g(a, b, .) end function r() return 1,2,3 end然后,我們有以下實(shí)參到形參的對(duì)應(yīng)關(guān)系: call parameters f(3) a=3, b=nil f(3, 4) a=3, b=4 f
46、(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, arg=n=0 g(3, 4) a=3, b=4, arg=n=0 g(3, 4, 5, 8) a=3, b=4, arg=5, 8; n=2 g(5, r() a=5, b=1, arg=2, 3; n=2結(jié)果使用 return 語(yǔ)句返回(見(jiàn) 2.4.4)。如果控制到達(dá)了函數(shù)尾部而沒(méi)有遇到 return 語(yǔ)句,那么函數(shù)沒(méi)有返回值。 冒號(hào)(:) 語(yǔ)法是用來(lái)定義 methods 的,也就是,函數(shù)有一個(gè)隱含的額外參數(shù) self. 。這樣,語(yǔ)句: funct
47、ion t.a.b.c:f (.) . end相對(duì)以下是較好的形式: t.a.b.c.f = function (self, .) . end2.6 - 可見(jiàn)性規(guī)則lua是一個(gè)有詞法范圍的語(yǔ)言。變量的范圍從聲明語(yǔ)句后的第一個(gè)語(yǔ)句開(kāi)始到包含聲明的最內(nèi)部的語(yǔ)句塊為止。例如: x = 10 - global variable do - new block local x = x - new x, with value 10 print(x) - 10 x = x+1 do - another block local x = x+1 - another x print(x) - 12 end prin
48、t(x) - 11 end print(x) - 10 (the global one)注意:在類似 local x = x,正在聲明的新的 x 尚未進(jìn)入范圍,所以第二個(gè) x 指代的是外面的變量。 由于詞法范圍的規(guī)則,在局部變量的范圍內(nèi)定義的函數(shù)可以任意訪問(wèn)這些變量。例如: local counter = 0 function inc (x) counter = counter + x return counter end內(nèi)部函數(shù)使用的局部變量在函數(shù)內(nèi)部稱之為 上值(upvalue),或者 外局部變量(external local variable)。 注意每個(gè) local 語(yǔ)句執(zhí)行時(shí)會(huì)定義一
49、個(gè)新的局部變量??匆韵吕樱?a = local x = 20 for i=1,10 do local y = 0 ai = function () y=y+1; return x+y end end循環(huán)產(chǎn)生了十個(gè)閉包(也就是,十個(gè)匿名函數(shù)的實(shí)例)。每個(gè)閉包使用不同的 y 變量,但他們共享同一個(gè) x 變量。 2.7 - 錯(cuò)誤處理因?yàn)閘ua是一個(gè)擴(kuò)展語(yǔ)言,所有的lua動(dòng)作都是從宿主程序中調(diào)用lua庫(kù)中函數(shù)的c代碼開(kāi)始的(見(jiàn) 3.15)。無(wú)論錯(cuò)誤發(fā)生在lua編譯過(guò)程時(shí)或執(zhí)行時(shí),控制返回c,然后可以做相應(yīng)的處理(比如打印一個(gè)錯(cuò)誤)。 lua代碼可以通過(guò)調(diào)用error函數(shù)來(lái)產(chǎn)生一個(gè)錯(cuò)誤(見(jiàn) 5.1)。
50、如果你要在lua中捕獲錯(cuò)誤,你可以使用 pcall 函數(shù)(見(jiàn) 5.1)。 2.8 - 元表 (metatables)lua中的每一個(gè)表和用戶數(shù)據(jù)都可以擁有一個(gè) 元表(metatable)。這個(gè) 元表 是一個(gè)普通的lua表,定義了在特定操作下原始表和用戶數(shù)據(jù)的行為。你可以通過(guò)設(shè)置一個(gè)對(duì)象的元表中的特定字段來(lái)更改它某些方面的行為。例如,當(dāng)一個(gè)對(duì)象是一個(gè)加法的操作數(shù)時(shí),lua檢查它的元表中的 _add 字段是不是一個(gè)函數(shù)。如果是,lua調(diào)用它來(lái)執(zhí)行加法。 我們稱元表中的鍵(字段名,key)為 事件(events) ,值為 元方法(metamethods)。在上一個(gè)例子中, add 是事件,執(zhí)行加法的函數(shù)是元方法。 你可以通過(guò) set/getmetatable 函數(shù)來(lái)查詢和更改一個(gè)對(duì)象的元表(見(jiàn) 5.1)。 元表可
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 直播帶貨產(chǎn)品課件
- 2025年熔化焊接與熱切割(復(fù)審)模擬考試題庫(kù)試卷
- 2024年長(zhǎng)沙客運(yùn)資格證模擬考試題庫(kù)下載電子版
- 2024年??诳蛙噺臉I(yè)考試題庫(kù)及答案
- 甘南市重點(diǎn)中學(xué)2025屆高一數(shù)學(xué)第一學(xué)期期末質(zhì)量跟蹤監(jiān)視模擬試題含解析
- 福建省師大附中2025屆高一生物第一學(xué)期期末教學(xué)質(zhì)量檢測(cè)模擬試題含解析
- 湖北省宜昌市長(zhǎng)陽(yáng)縣第一高級(jí)中學(xué)2025屆高三生物第一學(xué)期期末學(xué)業(yè)質(zhì)量監(jiān)測(cè)試題含解析
- 西塔塔吊施工方案科技雙優(yōu)化匯報(bào)
- 2025屆湖北省黃岡市浠水實(shí)驗(yàn)高中高三數(shù)學(xué)第一學(xué)期期末學(xué)業(yè)質(zhì)量監(jiān)測(cè)試題含解析
- 2025屆湖南省岳陽(yáng)縣一中、汨羅市一中生物高三上期末質(zhì)量跟蹤監(jiān)視試題含解析
- 審查意見(jiàn)答復(fù)模板
- 中考作文考前輔導(dǎo):意高文自勝
- 公司收購(gòu)聲明與承諾函
- 歷年北京市中小學(xué)生天文觀測(cè)競(jìng)賽_天文知識(shí)_小學(xué)組
- 語(yǔ)文論文淺談如何在語(yǔ)文教學(xué)中培養(yǎng)學(xué)生情感
- 危險(xiǎn)化學(xué)品安全使用許可適用行業(yè)目錄(2013年版)3
- 濕法脫硫工藝計(jì)算書(shū)
- 轎車子午線輪胎用簾線品種及其性能
- 天然氣室外立管吊裝專項(xiàng)施工方案(完整版)
- 淺談博物館布展設(shè)計(jì)的內(nèi)容與形式
- 在音樂(lè)教學(xué)中培養(yǎng)學(xué)生的人文素養(yǎng)
評(píng)論
0/150
提交評(píng)論