Dofile 命名空间提案

lua-users home
wiki

我发现 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"),但这有点违背了默认行为应该满足最常见情况(即调用者不是全局的)的经验法则。

提案详情


最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2006 年 11 月 28 日凌晨 3:56 GMT (差异)