《LUA程式設計》學習筆記__閱讀書籍筆記

來源:互聯網
上載者:User
第一章   開始

若使用命令列參數 -i 來啟動Lua解譯器,那麼解譯器就會在運行完指定程式塊後進入互動模式。例如在命令列中輸入:

% lua -i prog

這樣會先運行檔案prog中的程式塊,然後再進入互動模式。參數 -i 對於調試和手工測試尤為有用。


Lua中的標識符可以是由任意字母、數字和底線構成的字串,但不能以數字開頭。

應該避免使用以一個底線開頭並跟著一個或多個大寫字母(例如“_VERSION”)的標識符,Lua將這類別識別項保留用作特殊用途。通常保留標識符“_”(一個底線)作為“啞變數(Dummy Variable)”使用。


可以在任何地方以兩個連字號(--)開始一個“行注釋”,該注釋一直延伸到一行的結尾。Lua也提供了“塊注釋”,以“--[[”開始,直至“]]”。


Lua中有8種基礎類型:nil(空)、boolean(布爾)、number(數字)、string(字串)、userdata(自訂類型)、function(函數)、thread(線程)和table(表)。


Lua中的字串是不可變的值。不能像在C語言中那樣直接修改字串的某個字元,而是應該根據修改要求來建立一個新的字串。


可以用一對匹配的雙方括弧來界定一個字母字串,以這種形式書寫的字串可以延伸多行,Lua不會解釋其中的逸出序列。此外,如果字串的第一個字元是一個換行字串,那麼Lua會忽略它。這種書寫對於書寫那種含有程式碼的字串尤為有用。如下例:

page = [[<html><head><title>An HTML Page</title></head><body><a href="http://www.lua.org">lua</a></body></html>]]



第二章 類型與值

在table類型中,a.x和a[x]是不一樣的。前者表示a["x"],表示以字串“x”來索引table。而後者是以變數x的值來索引table。


雖然可以用任何值作為一個table的索引,也可以用任何數字作為數組索引的起始值。但就Lua的習慣而言,數組通常以1作為索引的起始值。並且有不少機制依賴於這個慣例。


在Lua5.1中,長度操作符“#”用於返回一個數組或線性表的最後一個索引值(或為其大小)。例如:

for i=1, #a do  print(a[i])end



注意:所有未初始化的元素的索引結果都是nil。Lua將nil作為界定數組結尾的標誌。當一個數組有“空隙”時,即中間含有nil時,長度操作符會認為這些nil元素就是結尾標誌。可以肯定我們不會想要這種不可預期性。因此應該避免對那些含有“空隙”的數組使用長度操作符。大多數數組不會包含“空隙”,因此大多數時候使用長度操作符是安全的。如果真的需要處理那些含有“空隙”的數組,可以使用函數table.maxn,它將返回一個table的最大正索引數。例如:

a = {}a[1000] = 1print(table.maxn(a))   --> 1000


在Lua中,函數是作為“第一類值”來看待的。這表示函數可以儲存在變數中,可以通過參數傳遞給其他函數,還可以作為其他函數的傳回值。


第三章 運算式

邏輯操作符有 and、or 和 not。與條件控制語句一樣,所有的邏輯操作符將 false 和 nil 視為假,而將其它的任何東西視為真。對於操作符 and 來說,如果它的第一個運算元為假,就返回第一個運算元;不然返回第二個運算元。對於操作符 or 來說,如果它的第一個運算元為真,就返回第一個運算元;不然返回第二個運算元。

print(4 and 5)  -->5print(nil and 13) -->nilprint(false and 13) -->falseprint(4 or 5) -->4print(false or 5) -->5



有一種常用的Lua習慣寫法“x=x or v”,它等價於:

if not x then   x = v end


它可用在沒有設定 x 的時候,將其設定為一個預設值 v。


另一種習慣寫法是“(a and b)or c”,這類似與C語言中的運算式 a?b:c,但前提是 b 不為假。例如,為了選出數字 x 和 y 中的較大者,可以使用以下語句:

max = (x>y) and x or y


要在Lua中串連兩個字串,可以使用操作符“..”,如果其任意一個運算元是數位話,Lua會將這個數字轉換成一個字串:

print("Hello" .. "world") -->Hello Worldprint(0 .. 1) -->01



每當Lua評估一個構造式時,都會先建立一個新table,然後初始化它。這樣,就能用table寫出以下的鏈表代碼:

list = nilfor line in io.lines() dolist = {next = list , value = line}end


這段代碼從標準輸入中讀取每行的內容,然後將每行按相反的次序儲存到一個鏈表中。鏈表的每個結點都是一個table,table中含有兩個欄位:value(每行的內容)和next(指向下一個結點的引用)。但在真實的Lua程式中很少會用到鏈表。


第四章 語句

在多重賦值中,Lua先對等號右邊的所有元素求值,然後才執行賦值。這樣便可以用一句多重賦值來互動兩個變數。如下所示:

x,y = y,x  -- 交換x與y


在Lua中,有一種習慣寫法是:

local foo = foo

這句代碼建立了一個局部變數foo,並將用全域變數foo的值初始化它。


Lua將0和Null 字元串也視為真。


因為那些位於return或break之後的語句將無法執行到,所以通常只能在上述幾個位置使用這些語句。然而有時可能希望在一個塊的中間插入一句return或break。例如,準備調試一個函數,但又不想執行該函數的內容。在這種情況中,可以使用一個顯示的do塊來包住一條return語句:

function foo()  return --<<語法錯誤  -- 在下一個塊中return就是最後一條語句  do return end--OK  <其它語句>end



第五章 函數

Lua會調整一個函數的傳回值數量以適應不同的調用情況。若將函數調用作為一條單獨語句時,Lua會丟棄函數的所有傳回值。若將函數作為運算式的一部分來調用時,Lua只保留函數的第一個傳回值。只有當一個函數調用是一系列運算式中的最後一個元素(或僅有一個元素)時,才能獲得它的所有傳回值。


第六章 深入函數

在Lua中,函數是一種“第一類值”,它們具有特定的詞法域。

“第一類值”:表示在Lua中函數與其他傳統類型的值(例如數字和字串)具有相同的權利。函數可以儲存到變數中(無論全域變數還是局部變數)或table中,可以作為實參傳遞給其它函數,還可以作為其它函數的傳回值。

“詞法域”:指一個函數可以嵌套在另一個函數中,內部的函數可以訪問外部函數中的變數。


第七章 迭代器與泛型for

所謂“迭代器”就是一種可以遍曆一種集合中所有元素的機制。在Lua中,通常將迭代器表示為函數。每調用一次函數,即返回集合中的“下一個”元素。

每個迭代器都需要在每次成功調用之間保持一些狀態,這樣才能知道它所在的位置及如何步入下一個位置。


泛型for在迴圈過程內部儲存了迭代器函數。實際上它儲存著3個值:一個迭代器函數、一個恒定狀態(invariant state)和一個控制變數(control variable)。

泛型for的文法如下:

for <var-list> in <exp-list> do  <body>end


其中,<var-list>是一個或多個變數名的列表,以逗號分隔;<exp-list>是一個或多個運算式的列表,同樣以逗號分隔。通常運算式列表只有一個元素,即一句對迭代器工廠的調用。例如,以下代碼:

for k,v in pairs(t) do print (k,v) end


其中變數列表是“k,v”,運算式列表只有一個元素pairs(t)。一般來說變數列表中也只有一個變數,例如下面這個迴圈:

for line in io.lines() do  io.write(line,"\n")end


變數列表的第一個元素稱為”控制變數”。在迴圈過程中該值決不會為nil,因為當它為nil時迴圈就結束了。

for做的第一件事情是對in後面的運算式求值。這些運算式應該返回3個值供for儲存:迭代器函數、恒定狀態和控制變數的初值。這裡有點類似於多重賦值,即只有最後一個運算式才會產生多個結果,並且只會保留前3個值,多餘的值會被丟棄;而不足的話,將以nil補足。

在初始化步驟之後,for會恒定狀態和控制變數來調用迭代器函數。然後for 將迭代器函數的傳回值賦予變數列表中的變數。如果第一個傳回值為nil,那麼迴圈終止。否則,for執行它的迴圈體,隨後再次調用迭代器函數,並重複這個過程。

更 明確地說,以下語句:

for var_1,...,var_n in <explist> do <block> end


等價於以下代碼:

do  local _f,_s,_var = <explist>  while true do    local var_1, ..., var_n = _f(_s, _var)    _var = var_1    if _var == nil then break end    <block>  endend


因此,假設迭代器函數為f,恒定狀態為s,控制變數的初值為a0。那麼在迴圈過程中控制變數的值依次為a1 = f(s,a0)、a2 = f(s,a1),依此類推,直至ai為nil結束迴圈。如果for還有其他變數,那麼它們也會在每次調用f後獲得額外的值。


第八章 編譯、執行與錯誤

儘管將Lua稱為是一種解釋型的語言,但Lua確實允許在運行原始碼前,先將原始碼先行編譯為一種中間形式。聽上去“編譯”似乎不應該在一種解釋型語言的範疇之列。其實,區別解釋型語言的主要特徵並不在於是否能編譯它們,而是在於編譯器是否是語言運行是庫的一部分,即是否有能力(並且輕易地)執行動態產生的程式碼。可以說正是因為存在了諸如dofile這樣的函數,才可以將Lua稱為是一種解釋型的語言。


當一個函數遭遇了一種未預期的狀況(即“異常”),它可以採取兩種基本的行為:返回錯誤碼(通常是nil)或引發一個錯誤(調用error)。在這兩種選擇之間並沒有固定的法則,但通常的指導原則是:易於避免的異常應引發一個錯誤,否則應返回錯誤碼。


第九章 協同程式

協同程式與線程差不多,也就是一條執行序列,擁有自己獨立的棧、局部變數和指令指標,同時又與其他協同程式共用全域變數和其他大部分東西。從概念上講線程與協同程式的主要區別在於,一個具有多個線程的程式可以同時運行幾個線程,而協同程式卻需要彼此協作地運行。就是說,一個具有多個協同程式的程式在任意時刻只能運行一個協同程式,並且正在啟動並執行協同程式只會在其顯式地要求掛起時,它的執行才會暫停。


一個協同程式可以處於4種不同的狀態:掛起、運行、死亡和正常。當建立一個協同程式時,它處於掛起狀態。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.