第一版是为 Lua 5.0 编写的。虽然在很大程度上仍然适用于后续版本,但也有一些区别。
第四版针对 Lua 5.3,可在 亚马逊 和其他书店购买。
购买本书,您还将帮助支持 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 或 nil),assert
会引发错误。它的第二个参数(消息)是可选的,因此如果您不想在错误消息中说任何内容,则不必说。但是,请注意,assert
是一个常规函数。因此,Lua 始终在调用函数之前计算其参数。因此,如果您有类似以下内容:
n = io.read() assert(tonumber(n), "invalid input: " .. n .. " is not a number")即使
n
是一个数字,Lua 也会始终执行连接。在这种情况下,最好使用显式测试。
当一个函数发现意外情况(一个异常)时,它可以采取两种基本行为:它可以返回一个错误代码(通常为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。保留所有权利。 |