这是一个bug还是特性?Lua@OpenComputers@minecraft。

为什么“load”没有从环境中获取编译块的环境?

局部变量 e 包含了三个键值对,其中 print 函数、 load 函数,以及字符串 "2" 的键值对。 e._G=e 将全局环境引用设为 e

load 函数接收三个额外参数 ''''e,表示传递了一个空源名、一个空模式串和由 e 确定的环境。

load 执行源码 print(a) \n load("print(a)")() ,其主要意图为:打印局部变量 a 的值,加载一个新的源代码 "print(a)",执行新的代码。

在执行源码的过程中,第一行 print(a) 成功地打印出了局部变量 a 的值 —— 字符串 "2",因为该行代码所处的环境就是 e。而在第二行 load("print(a)")() 中,由于没有通过参数传递环境,所以加载的源码执行时使用的环境是 print 函数所在的默认环境—— e._G

因此,此行代码打印出来的局部变量 a 的值是 1,因为在默认环境 e._G 中没有 a 这个变量。

整个程序的最终输出结果是两行:

2
1
点赞
用户3125367
用户3125367

如果结果函数有 upvalues,那么第一个 upvalue 将会被设为 env 参数给定的值,如果没有给出参数,其将被设为全局环境的值。

也就是说,无论你现在在 _ENV 中的位置是什么,如果没有给 load 函数传递 env 参数,那么加载的代码块将会连接到全局环境。

如果你想要在 5.2 版本中加载的源代码默认继承一个新环境,可以使用以下代码替换 load / loadfile 函数:

e.load = function (ld, src, mode, env)
    return load(ld, src, mode, env or e)
end
2015-06-25 00:36:17