第一版是針對 Lua 5.0 編寫的。雖然在很大程度上仍然適用於後續版本,但仍有一些差異。
第四版針對 Lua 5.3,可在 Amazon 和其他書店購買。
購買本書,您也協助 支援 Lua 專案


8.3 – 錯誤

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(也就是 falsenil),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 的第二個引數。