0x07编译、执行与错误
Lua虽然是一种解释性语言,但Lua允许在运行源码前,先将源码预编译成一种中间形式。
1.编译与执行
Lua提供了dofile
loadfile
两个接口来从文件里加载Lua的代码块,但它不会运行代码,而只是编译做对,然后将编译结果作为一个函数返回
function dofile (filename)
local f = assert(loadfile(filename))
return f()
end
注:如果dofile
失败,那么其中的assert
就会引发一个错误
loadstring
与loadfile
类似,但是不同的一点是,loadfile
是对一个文件进行读取的而loadstring
是对一个字符串来进行读取的。
loadstring功能非常的强大,但应该谨慎使用,因为他是一个开销较大的函数
f = loadstring("i = i + 1") --Code 1
上面的代码等价于下面的代码
f = function() i = i + 1 end --Code 2
- Code1 和 Code2的代码是类似的,但是Code2的代码会快很多,因为它只在编译对应程序块时被编译了一次。而Code1却在每次调用
loadstring()
时都被重新编译。 - Code1与Code2严格来说是不等价的,因为loadstring在编译时不涉及词法域
i = 32
local i = 0
f = loadstring("i = i + 1; print(i)")
g = function() i = i + 1; print(i) end
f() -->33
g() -->1
loadstring
最大的用处是用来处理来自外部输入的代码,如用户自定义的程序
匿名函数
Lua将所有独立的程序块视为一个匿名函数的函数体,并且该匿名函数还具有可变长实参。例如loadstring(“a=1”)返回的结果等价于以下表达式:
function(...) a = 1 end
loadstring
loadfile
对传入的参数编译后将结果作为一个匿名函数返回。
如有一个foo.lua文件:
function foo (x)
print(x)
end
然后执行下面的代码:
f = loadfile("foo.lua")
在此之后,函数完成编译,但是还没定义它。
print(foo) -->nil
f() -->定义了foo
foo("ok") -->ok
其它:loadlib函数加载指定的库,并将其直接链接入Lua
2.错误及错误处理
由于Lua是一种扩展语言,通常嵌入在应用程序中,因此在发生错误时它不能简单地崩溃或者退出
通过error
来处理错误
print "enter a number:"
n = io.read("*number")
if not n then error("invalid input") end
--或者使用assert
--n = assert(io.read("*number"), "invalid input")
当一个行为发生异常时,通常有两种处理方法:1.返回错误代码(通常是nil) 2.引发一个错误(调用error
)
如果需要在Lua中处理错误,则必须使用函数pcall
来包装需要执行的代码
function foo()
<some code>
<some code> print(a[i]) --潜在的错误:a为需要打印的错误信息
<some code>
end
然后用pcall
调用foo
:
if pcall(foo) then
--执行时没有发生错误
<正常代码>
else
--foo发生错误,处理异常
<错误处理代码> end