load在加载代码块时,通常使用全局环境去初始化代码块的_ENV上值。
然而,load选项的第四个参数给出的值就是供_ENV用的。(loadfile函数参数也是一样)
举一个有关初始化的例子,假如我们有一个普通的配置文件,定义了一些常量和函数供程序使用。
--file 'config.lua ' width = 200 height = 300 ...
然后用下面的代码加载:
env = { } f = loadfile("config.lua","t",env) f()
配置文件中的代码就会在空环境env中运行。
有时,需要多次运行同一块代码,每次运行的环境表都不同。
上面的情况中,load的额外参数就满足不着了。有两个选择可以满足该需求:
第一个,使用debug库的debug.setupvalue 函数。允许改变给定函数的任何上值:
f = loadfile(name) ... env = { } gebug. setupvalue(f,1,env)
该函数的第一个参数是函数,第二个参数是上值的索引,第三个参数是upvalue的新值。
对于修改环境变量的情况:就是针对第一个参数是load 或loadfile 返回的一个函数,Lua会保证它只有唯一的一个_ENV 上值。这时setupvalue 的第二个参数永远是1。
这种情况的选择有一个不好的缺点是依赖debug库。
第二个选择,就是在加载代码前做点手脚。比如加载前加上下面的一行代码:
_ENV = ...
之前提到过,Lua 编译代码块时,把它当作变参函数。因此,上面的那一行代码会被当作chunk代码块的第一个参数。
因此就用它设置了环境。加载完这段代码块,我们再调用执行代码块后的返回函数。该函数就完成了把目标环境当作第一个参数传递过去。例如:
f = loadwithprefix("local _ENV = ...;",io.lines(filename,"*L")) ... env = {} f(env)