Lua爬坑手記

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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章