第一版是針對 Lua 5.0 編寫的。雖然在很大程度上仍然適用於後續版本,但仍有一些差異。
第四版針對 Lua 5.3,可在 Amazon 和其他書店購買。
購買本書,您也協助 支援 Lua 專案。
![]() |
用 Lua 程式設計 | ![]() |
第一部。語言 第 8 章。編譯、執行和錯誤 |
Errare humanum est。因此,我們必須盡可能以最佳方式處理錯誤。由於 Lua 是延伸語言,經常會嵌入在應用程式中,因此當錯誤發生時,它無法單純當機或結束。相反地,每當錯誤發生時,Lua 會結束目前的區塊並返回應用程式。
Lua 會遇到的任何意外狀況都會引發錯誤。當您(也就是您的程式)嘗試將非數字值相加、呼叫非函數值、索引非資料表值等時,就會發生錯誤。(您可以使用 元資料表 修改此行為,我們稍後會說明。)您也可以呼叫 error
函數來明確引發錯誤;其引數是錯誤訊息。通常,此函數是處理程式碼中錯誤的適當方式
print "enter a number:" n = io.read("*number") if not n then error("invalid input") end
if not ... then error end
的組合很常見,因此 Lua 有內建函數專門用於此工作,稱為 assert
print "enter a number:" n = assert(io.read("*number"), "invalid input")
assert
函數檢查其第一個引數是否不為 false,並單純傳回該引數;如果引數為 false(也就是 false 或 nil),assert
會引發錯誤。其第二個引數(訊息)是選用的,因此如果您不想要在錯誤訊息中說任何話,您不必這麼做。不過,請注意 assert
是常規函數。因此,Lua 會在呼叫函數前先評估其引數。因此,如果您有類似
n = io.read() assert(tonumber(n), "invalid input: " .. n .. " is not a number")Lua 會永遠執行串接,即使
n
是數字。在這種情況下,最好使用明確測試。
當函數發現意外狀況(例外)時,它可以假設兩種基本行為:它可以傳回錯誤碼(通常為 nil),或它可以呼叫 error
函數來引發錯誤。沒有固定的規則可供選擇這兩個選項,但我們可以提供一個一般準則:可以輕易避免的例外應引發錯誤;否則,它應傳回錯誤碼。
例如,我們來考慮 sin
函數。當呼叫資料表時,它應如何表現?假設它傳回錯誤碼。如果我們需要檢查錯誤,我們必須寫類似
local res = math.sin(x) if not res then -- error ...不過,我們可以在呼叫函數之前輕鬆地檢查這個例外
if not tonumber(x) then -- error: x is not a number ...然而,我們通常不會檢查
sin
呼叫的引數或結果;如果引數不是數字,這表示我們的程式中可能有些錯誤。在這種情況下,停止運算並發出錯誤訊息是最簡單且最實用的例外處理方式。
另一方面,讓我們考慮開啟檔案的 io.open
函數。當呼叫它來讀取不存在的檔案時,它應該如何運作?在這種情況下,沒有簡單的方法可以在呼叫函數之前檢查例外。在許多系統中,唯一知道檔案是否存在的方法就是嘗試開啟它。因此,如果 io.open
由於外部原因(例如 "檔案不存在"
或 "權限遭拒"
)而無法開啟檔案,它會傳回 nil,以及包含錯誤訊息的字串。透過這種方式,您可以適當地處理情況,例如詢問使用者另一個檔案名稱
local file, msg repeat print "enter a file name:" local name = io.read() if not name then return end -- no input file, msg = io.open(name, "r") if not file then print(msg) end until file如果您不想處理這種情況,但仍想安全起見,您只需使用
assert
來保護操作
file = assert(io.open(name, "r"))這是典型的 Lua 慣用語:如果
io.open
失敗,assert
會引發錯誤。
file = assert(io.open("no-file", "r")) --> stdin:1: no-file: No such file or directory請注意,
io.open
的第二個結果(錯誤訊息)會作為 assert
的第二個引數。
版權所有 © 2003–2004 Roberto Ierusalimschy。保留所有權利。 | ![]() |