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

提案详情


RecentChanges · preferences
编辑 · 历史
最后编辑于 2006 年 11 月 27 日下午 9:56 GMT (差异)