Dofile 命名空间提案 |
|
举个实际例子,我有一个嵌入了 Lua 的应用程序,并为用户设置了一个命名空间来运行代码。用户可能想加载和运行其他代码,但 dofile 对用户来说在这里并不真正起作用,因为 dofile 操作的是调用代码可能甚至看不到的全局命名空间,并将结果放入其中。用户可能甚至不知道自己在本地命名空间下运行(有人可能会争辩说,他也不应该知道)。因此,我的应用程序为用户设置了一个名为 myapp.import 的新函数,其基本定义如下:
function myapp.import(name) local f,e = loadfile(name) if not f then error(e, 2) end setfenv(f, getfenv(2)) return f() end
但其中一个用户刚刚报告说 dofile 并不能按他们想要的执行(实际上可能是第二个用户),我回应说他们应该改用 myapp.import,所以显然存在一些困惑,而且相当一部分人可能对 Lua 命名空间不够熟悉,无法理解原因。尽管如此,我想知道为什么 dofile 最初不按照我想要的方式运行,以避免这个问题。
RiciLake 表示同意,并指出当前的行为有些过时(即其语义指的是 Lua 的旧版本)。
为了减少困惑,我的一个选择是将 dofile 重定义如下:
function dofile() error("Use myapp.import(name) instead of dofile(name)", 2)
或者,可能更不容易混淆,但对内置语义进行少量更改,我可以在本地命名空间中重定义 dofile,如下所示。我试图避免语义上的更改,但也许它是可以接受的,因为当用户拥有一个非常好的本地命名空间时,他们可能根本就不应该使用修改全局命名空间的原有语义。
dofile = myapp.import
另外,这个更改也可以在 Lua 本身中进行,但当然它可能会(是否会?)破坏现有代码。另一个选项可能是允许一个额外的参数来指定命名空间,例如 dofile("hello.lua", "caller"),但这有点违背了默认行为应该满足最常见情况(即调用者不是全局的)的经验法则。
提案详情