Lua程序设计(二十七)
编译、执行和错误
解释型语言的区分并不在于源码是否被编译,而在于是否有能力(且轻易地)执行动态生成的代码。
编译
函数dofile是运行Lua代码段的主要方式之一。实际上,函数dofile是一个辅助函数,函数loadfile才完成了真正的核心工作。
函数loadfile也是从文件中加载Lua代码段,但它不会运行代码,而只是编译代码,然后将编译后的代码段作为一个函数返回。
可以将函数dofile理解为如下代码:
function dofile (filename)
local f = assert(loadfile(filename))
return f()
end
函数loadfile更灵活。在发生错误的情况中,函数loadfile可以返回nil及错误信息,以便我们可以按照自定义的方式来处理错误。此外,如果需要多次运行同一个文件,那么只需要调用一次loadfile函数后再多次调用它的返回结果即可。这种方式的开销将比多次调用函数dofile小得多。
函数load与函数loadfile类似,不同之处在于该函数从一个字符串或者函数中读取代码段,而不是从文件中读取。函数load是最典型的用法是执行外部代码(即那些来自程序本身之外的代码段)或动态生成的代码。
print "enter your expression:"
local line = io.read()
local func = assert(load("return" .. line))
print("the value of your expression is: " .. func())
由于函数 load 所返回的还是要就是一个普通函数,因此可以反复对其进行调用。
print "enter function to be plotted (with variable 'x'):"
local line = io.read()
local f = assert(load("return" .. line))
for i = 1, 20 do
x = i
print(string.rep("*", f()))
end
我们也可以使用读取函数 reader function 作为函数load的第一个参数。函数load会不断地调用读取函数直到返回nil.
Lua语言将所有独立的代码段当做匿名可变长函数的函数体。像其他任何函数一样,代码段中可以声明局部变量,使用这个特性,可以在不使用全局变量x的情况下重写之前运行用户定义函数的示例
函数load和函数loadfile从来不引发错误。当有错误发生时,它们将返回nil及错误信息。这些函数知识将程序段编译为一种中间形式,然后将结果作为匿名函数返回。
一种常见的误解是认为加载一段程序也就是定义了函数,但实际上Lua语言中函数定义是在运行时而不是编译时发生的一种复制操作。