大家在使用 Lua 的時候,一定會遇到不少和 nil 有關的坑吧。有時候不小心引用了一個沒有賦值的變量,這時它的值默認為 nil。如果對一個 nil 進行索引的話,會導致異常。
如下:
local person = {name = "Bob", sex = "M"}
-- do something
person = nil
-- do something
print(person.name)
上面這個例子把 nil 的錯誤用法顯而易見地展示出來,執(zhí)行后,會提示下面的錯誤:
stdin:1:attempt to index global 'person' (a nil value)
stack traceback:
stdin:1: in main chunk
[C]: ?
然而,在實際的工程代碼中,我們很難這么輕易地發(fā)現(xiàn)我們引用了 nil 變量。因此,在很多情況下我們在訪問一些 table 型變量時,需要先判斷該變量是否為 nil,例如將上面的代碼改成:
local person = {name = "Bob", sex = "M"}
-- do something
person = nil
-- do something
if person ~= nil and person.name ~= nil then
print(person.name)
else
-- do something
end
對于簡單類型的變量,我們可以用 if (var == nil) then 這樣的簡單句子來判斷。但是對于 table 型的 Lua 對象,就不能這么簡單判斷它是否為空了。一個 table 型變量的值可能是 {}
,這時它不等于 nil。我們來看下面這段代碼:
local next = next
local a = {}
local b = {name = "Bob", sex = "Male"}
local c = {"Male", "Female"}
local d = nil
print(#a)
print(#b)
print(#c)
--print(#d) -- error
if a == nil then
print("a == nil")
end
if b == nil then
print("b == nil")
end
if c == nil then
print("c == nil")
end
if d== nil then
print("d == nil")
end
if next(a) == nil then
print("next(a) == nil")
end
if next(b) == nil then
print("next(b) == nil")
end
if next(c) == nil then
print("next(c) == nil")
end
返回的結果如下:
0
0
2
d == nil
next(a) == nil
因此,我們要判斷一個 table 是否為 {}
,不能采用 #table == 0
的方式來判斷??梢杂孟旅孢@樣的方法來判斷:
function isTableEmpty(t)
return t == nil or next(t) == nil
end
注意:next
指令是不能被 LuaJIT 的 JIT 編譯優(yōu)化,并且 LuaJIT 貌似沒有明確計劃支持這個指令優(yōu)化,在不是必須的情況下,盡量少用。