0x00 爬坑說明書
最近編寫遊戲的客戶端邏輯,部分以Lua爲主,介於使用的Lua的經驗尚淺,也就邊寫邊看《Lua程序設計》。書中有些知識點真的是過目即忘,發現Lua還是有一些坑,下面權當作是Lua的爬坑筆記。
0x01 Lua的類型
最近一次在處理UGUI中ScrollView控件動態生成的對象時,利用動態生成的對象後綴來作爲後續計算的索引。代碼類似:
function ConvertGameObjectIndex2Param(go)
local data_index = string.match(go, '%d')
print('data_index:', data_index) -- 1
end
ConvertGameObjectIndex2Param("obj1")
其中data_index是計算得出的索引,在後續的運算中卻始終索引不到data_index在table中對應的值,由於data_index輸出的log顯示正常,起初並沒有懷疑到這裏。排查數據源確信沒有問題後,我總記得在《Lua程序設計》中看到過一段作者列舉table中各種索引使用的代碼:
果然是紙上得來終覺淺,絕知此事要躬行啊。遂打印data_index的類型:
function ConvertGameObjectIndex2Param(go)
local data_index = string.match(go, '%d')
print('date_index:', data_index, type(data_index)) -- 1 string
data_index = tonumber(data_index)
print('date_index:', data_index, type(data_index)) -- 1 number
end
使用tonumber()轉換爲number類型後,問題解決。
0x01 你到底是什麼類型?
上述代碼段data_index第一次的類型是string,進行轉換後data_index的類型變成了number。熟悉動態類型語言的coder對於此情此景應該已經見怪不怪了。而我等半截入土的古董從C/C++而來,總是感覺哪裏不太對。明明聲明的時候是string怎麼後面還會變成number呢?
這是Lua靈活的地方,也是容易混淆的地方,用好了可以節省時間,用不好堪比C語言中的野指針。以至於我這幾天在所有要通過number類型索引數據的地方,都會心驚膽戰的先用tonumber()轉了它再說。
0x02 table數據的讀取
最初看到table,總是會執迷於去窺探“關聯數組”的實現方式。而日常的使用中,卻連最基本的使用方式都拎不清,真是“臉紅”。不信你看下面這段代碼輸出什麼呢?
local test_table = {}
index = 1
test_table[index] = "data_num"
test_table["index"] = "data_str"
print('test_table[index]', test_table[1]) -- data_num
print('test_table["index"]', test_table["index"]) -- data_str
print('test_table.index', test_table.index) -- data_str
要注意test_table.index是與test_table[“index”]完全等價的。上面的是不是so easy?那麼進階版來了:
local test_table = {}
local num_index = 1
local str_index = "1"
test_table[num_index] = 'data_num'
test_table[str_index] = 'data_str'
print('test_table[num_index]', test_table[num_index]) -- data_num
print('test_table[str_index]', test_table[str_index]) -- data_str
print('test_table.num_index', test_table.num_index) -- nil
print('test_table.str_index', test_table.str_index) -- nil
print('test_table[tostring(num_index)]', test_table[tostring(num_index)]) -- data_str
print('test_table[tonumber(str_index)]', test_table[tonumber(str_index)]) -- data_num
print('test_table[1]', test_table[1]) -- data_num
print('test_table[01]', test_table[01]) -- data_num
print('test_table["01"]', test_table["01"]) -- nil
據說搞懂上面這一堆亂七八糟的東西可以召喚神龍!
0x03 自動轉換之殤
Lua提供了數字與字符串之間的自動轉換,對一個字符串進行算術運算時,Lua會將這個字符串轉換成一個數字:
local temp = '10' + 1
print(temp, type(temp)) -- 11 number
temp = '10 + 1'
print(temp, type(temp)) -- 10 + 1 string
Lua中還有字符串連接操作符..,當..出現在數字後面時,需要額外添加一個空格,以免Lua將之與小數點混淆:
temp = 10 .. 20
print(temp, type(temp)) -- 1020 string
0x04 真亦假,假亦真
在Lua中將false與nil視爲假,其他都爲真。那麼從C/C++過來搞事情的程序員最容易碰到什麼問題呢?當然是數字0和空字符串拉。那怎麼辦呢?當然是選擇原諒他!
local condition1 = true
local condition2 = 0
local condition3 = ""
local condition4 = false
local condition5 = nil
if condition1 then print('condition1:', condition1) end -- true
if condition2 then print('condition2:', condition2) end -- 0
if condition3 then print('condition3:', condition3) end
if not condition4 then print('condition4:', condition4) end -- false
if not condition5 then print('condition5:', condition5) end -- nil