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