Lua極簡入門指南(三): loadfile和錯誤處理

NO IMAGE

編譯

Lua 雖然是解釋性語言,但 Lua 原始碼總是被編譯為中間形式後再執行。

dofile 用於載入並執行一個 Lua 檔案,相比之下,loadfile 用於載入一個 Lua 檔案,但並不執行,確切的說 loadfile 編譯了一個 chunk,並返回此被編譯的 chunk(被作為一個函式):

複製程式碼 程式碼如下:
c = loadfile(‘./test.lua’)
c()

dofile 可以被實現為:

複製程式碼 程式碼如下:
function dofile(filename)
    local f = assert(loadfile(filename))
    return f()
end

一個類似 loadfile 的函式 load,它使用字串(而非檔案)作為引數,返回被編譯的 chunk:

複製程式碼 程式碼如下:
f = load(‘i = i 1’)
i = 0
f(); print(i)  –> 1
f(); print(i)  –> 2

另外,我們可以使用命令 luac 來直接編譯 Lua 檔案:

複製程式碼 程式碼如下:
luac -o prog.lc prog.lua
lua prog.lc

錯誤

Lua 遇見任何不可接受的條件時會產生錯誤。例如:

複製程式碼 程式碼如下:
local t = {}
— 出錯
t = t 1

我們可以顯式的呼叫 error 函式來產生一個錯誤,error 接受一個錯誤訊息作為引數:

複製程式碼 程式碼如下:
print ‘enter a number:’
n = io.read(‘*n’)
if not n then error(‘invalid input’) end

assert 函式也可以產生錯誤。assert 函式檢查第一個引數是否為 false,如果不為 false 就返回此引數,如果為 false 就產生一個錯誤。assert 的第二個引數,錯誤訊息,是可選的。範例:

複製程式碼 程式碼如下:
n = io.read()
assert(tonumber(n), ‘invalid input: ‘ .. n .. ‘ is not a number’)

pcall 函式可以捕獲錯誤:
複製程式碼 程式碼如下:
local ok, msg = pcall(function()
    assert(false)
end)
 
print(ok, msg)

pcall 函式使用保護模式(protected mode)呼叫第一個引數(此引數為一個函式),如果被呼叫的函式執行不存在錯誤,pcall 返回 true 並返回被呼叫函式的所有返回值,如果被呼叫的函式產生了錯誤,pcall 返回 false 並附帶上錯誤訊息。嚴格來說,錯誤訊息不一定需要是字串:
複製程式碼 程式碼如下:
local ok, err = pcall(function()
    error({code = 502})
end)
 
print(err.code)

追蹤錯誤

我們先看一個函式:
複製程式碼 程式碼如下:
function foo(str)
    if type(str) ~= ‘string’ then
        error(‘string expected’)
    end
    — …
end
 
foo(1)

foo 函式需要一個字串引數,我們執行上面的程式碼:
複製程式碼 程式碼如下:
lua: test.lua:3: string expected

輸出指出了錯誤出現在 foo 函式中(因為 foo 函式呼叫了 error),而實際上,錯誤是 foo 的呼叫者產生的,而非 foo 產生的。我們可以設定 level 來修正這個報錯:

複製程式碼 程式碼如下:
function foo(str)
    if type(str) ~= ‘string’ then
        error(‘string expected’, 2)
    end
    — …
end

error 函式的第二個引數為 level,用於指定報錯的位置,level 值為 1 表示 error 的呼叫者,值為 2 表示 error 的呼叫者的呼叫者,以此類推。

pcall 只能返回錯誤訊息,很多時候我們需要完整的呼叫棧,這時可以使用 xpcall 函式。xpcall 函式可以接收一個訊息 handler 作為引數,在被呼叫函式出現錯誤時,訊息 handler 會被呼叫,通過其就可以獲取到當前呼叫棧的資訊。

您可能感興趣的文章:

Lua指令碼語言簡明入門教程Lua極簡入門指南(一):基礎知識篇Lua極簡入門指南(一):函式篇Lua極簡入門指南:全域性變數lua指令碼語言快速入門教程Lua入門學習筆記Lua極簡入門指南(六):模組Lua 極簡入門指南(七):物件導向程式設計Lua指令碼語言基本語法快速入門教程Lua語言新手簡單入門教程