本文是《Programming in Lua 3rd》讀書筆記。
Chunks
一個(gè) Chunk 就是一組被執(zhí)行的語句,例如一個(gè)文件或者交互模式下的一行。
標(biāo)識(shí)符(identifiers)
我們應(yīng)該避免使用以 _ 開頭并跟上一個(gè)或者多個(gè)大寫字母的字符串來作標(biāo)識(shí)符,它們被保留作特殊的用途(例如:_VERSION)。
注釋
單行注釋使用
類型簡(jiǎn)介
Lua 存在的數(shù)據(jù)類型包括:
1.nil。此類型只有一個(gè)值 nil。用于表示“空”值。全局變量默認(rèn)為 nil,刪除一個(gè)已經(jīng)賦值的全局變量只需要將其賦值為 nil(對(duì)比 JavaScript,賦值 null 并不能完全刪除對(duì)象的屬性,屬性還存在,值為 null)
2.boolean。此類型有兩個(gè)值 true 和 false。在 Lua 中,false 和 nil 都表示條件假,其他值都表示條件真(區(qū)別于 C/C++ 等語言的是,0 是真)
3.number。雙精浮點(diǎn)數(shù)(IEEE 754 標(biāo)準(zhǔn)),Lua 沒有整數(shù)類型
4.string。你可以保存任意的二進(jìn)制數(shù)據(jù)到字符串中(包括 0)。字符串中的字符是不可以改變的(需要改變時(shí),你只能創(chuàng)建一個(gè)新的字符串)。獲取字符串的長(zhǎng)度,可以使用 # 操作符(長(zhǎng)度操作符)。例如:print(#”hello”)。字符串可以使用單引號(hào),也可以使用雙引號(hào)包裹,對(duì)于多行的字符串還可以使用 [[ 和 ]] 包裹。字符串中可以使用轉(zhuǎn)義字符,例如 /n /r 等。使用 [[ 和 ]] 包裹的字符串中的轉(zhuǎn)義字符不會(huì)被轉(zhuǎn)義
5.userdata。用于保存任意的 C 數(shù)據(jù)。userdata 只能支持賦值操作和比較測(cè)試
6.function。函數(shù)是第一類值(first-class value),我們能夠像使用其他變量一樣的使用函數(shù)(函數(shù)能夠保存在變量中,可以作為參數(shù)傳遞給函數(shù))
7.thread。區(qū)別于我們常常說的系統(tǒng)級(jí)線程
8.table。被實(shí)現(xiàn)為關(guān)聯(lián)數(shù)組(associative arrays),可以通過任何值來進(jìn)行索引(nil 除外)。和全局變量一樣,table 中未賦值的域?yàn)?nil,刪除一個(gè)域只需要將其賦值為 nil(實(shí)際上,全局變量就是被放置在一個(gè) table 中)
type 函數(shù)用于返回值的類型:
在 Lua 中,任何的變量都可以保存任何的值。
table 使用簡(jiǎn)介
使用構(gòu)造表達(dá)式可以創(chuàng)建一個(gè) table:
使用 [] 操作符訪問 table 的域:
注意,a.name 的語法等價(jià)于 a["name"]。
table 可以用于表示數(shù)組,這時(shí)候索引為整數(shù),并且從 1(而非 0)開始,例如:
長(zhǎng)度操作符可以獲取 table 數(shù)組部分的長(zhǎng)度:
表達(dá)式
算術(shù)操作符
1.+(加)
2.-(減)
3.*(乘)
4./(除)
5.^(冪)
6.%(取模)
任何算術(shù)操作符都試圖將操作數(shù)轉(zhuǎn)換為數(shù)值類型,例如:
關(guān)系操作符
1.<(小于)
2.>(大于)
3.<=(小于等于)
4.>=(大于等于)
5.==(等于)
6.~=(不等于)
兩個(gè)不同類型的值是不相等的,例如:
table、userdata 類型是通過引用進(jìn)行比較的,例如:
這里 a 和 c 引用一個(gè)相同的對(duì)象,因此 a == c,但是 a ~= b(即便 a、b 內(nèi)容相同)。
邏輯操作符
1.and
2.or
3.not
邏輯操作符有返回值。對(duì)于 and 操作來說,如果第一個(gè)操作數(shù)為 false 時(shí)返回此操作數(shù),否則返回第二個(gè)操作數(shù)。對(duì)于 or 操作來說,如果第一個(gè)操作數(shù)不為 false 時(shí)返回此操作數(shù),否則返回第二個(gè)操作數(shù)。
連接操作符
字符串連接可以使用連接操作符 “..”,例如:
語句
多賦值(multiple assignment)支持,例如:
局部變量的作用域限制于他們聲明的塊(block)。塊(block)包括:
1.控制結(jié)構(gòu)的主體部分
2.函數(shù)體
3.chunk
4.do-end
范例:
1.避免某些類型的全局變量被修改
2.提高訪問速度
控制結(jié)構(gòu)
if then elseif else
Lua 中沒有 switch 語句。
while
repeat
區(qū)別于 while,repeat 會(huì)先執(zhí)行循環(huán)體,然后判斷測(cè)試條件。
數(shù)值型 for(numeric for)
for 有兩種:
數(shù)值型 for(numeric for)
1.泛型 for(generic for)
2.數(shù)值型 for 的語法如下:
有一些需要注意的地方:
1.for 中的 exp1、exp2、exp3 只會(huì)被計(jì)算一次值,例如:
2.控制變量 var 只是一個(gè)局部變量
3.不要嘗試去修改控制變量 var 的值(結(jié)果是未知的)
泛型 for
泛型 for 通過一個(gè)迭代器函數(shù)來實(shí)現(xiàn)遍歷,例如:
這里的 pairs 就是一個(gè)迭代器函數(shù),此 for 循環(huán)遍歷 table t,每次獲取到的 key 保存在變量 k 中,獲取到的 value 保存在變量 v 中。除了 pairs 還有其他的迭代器可以用:
1.io.lines 可用于迭代文件中的行
2.ipairs 可用于迭代 table 的數(shù)組部分
我們還可以自己編寫迭代器。
break、return、goto
break 語句用于跳出一個(gè)循環(huán)(for、repeat、while)。
return 語句用于為函數(shù)返回結(jié)果。在 Lua 中,return 語句必須是一個(gè)塊的最后一條語句,看一個(gè)例子:
有時(shí)候,我們出于某些原因(例如為了 debug),我們需要在一個(gè)函數(shù)中插入一個(gè) return 語句,這時(shí)候可以這么做:
goto 語句用于在函數(shù)中跳轉(zhuǎn)。goto 語句可以讓執(zhí)行跳轉(zhuǎn)到特定的標(biāo)簽(label)處,例如:
這里輸出 quit。正如我們看到的,標(biāo)簽的寫法為 ::name::。goto 跳轉(zhuǎn)也是存在限制的:
1.不允許跳轉(zhuǎn)到一個(gè)塊中去
2.不允許跳轉(zhuǎn)到函數(shù)之外去
3.不允許跳入局部變量的作用域中
對(duì)于第三點(diǎn),看一個(gè)例子:
這里,會(huì)出現(xiàn)語法錯(cuò)誤(jumps into the scope of local 'a')。但是,有一個(gè)細(xì)節(jié)需要注意,我們先修改上面的例子:
執(zhí)行成功,沒有語法錯(cuò)誤。這是因?yàn)榫植孔兞康淖饔糜蚪Y(jié)束于變量定義的塊的最后一個(gè)非 void 語句,而標(biāo)簽被認(rèn)為是一個(gè) void 語句,對(duì)于上面的例子來說,a 的作用域在 ::quit:: 之前就結(jié)束了,因此 goto quit 并沒有跳入局部變量 a 的作用域中。
利用 goto 可以比較方便的編寫狀態(tài)機(jī),例如(s1、s2 為狀態(tài)):
新聞熱點(diǎn)
疑難解答
圖片精選