Dofile Namespace Proposal |
|
For a real example, I have an application that embeds Lua and sets up a namespace for the user to run code under. The user may want to load and run yet other code, but dofile
will not really work here for the user since dofile
operates on and puts results into the global namespace that the calling code might not even see. The user might not even be aware of operating under a local namespace (nor should he, one might argue). Therefore, my application sets up for the user a new function myapp.import defined basically as follows:
function myapp.import(name) local f,e = loadfile(name) if not f then error(e, 2) end setfenv(f, getfenv(2)) return f() end
But one such user just reported that dofile
does not do what they want (actually probably the second user), and I responded that they should use myapp.import instead, so there's obviously some confusion, and a good number probably aren't enough familiar with Lua namespaces to have understood why. Still, I wonder why dofile
doesn't behave the way I want it to in the first place to avoid the issue.
RiciLake agreed, noting that the current behavior was a bit anachronistic (i.e. its semantics refer to older versions of Lua).
To reduce confusion, one option I have is to redefine dofile
as such:
function dofile() error("Use myapp.import(name) instead of dofile(name)", 2)
Or, possibly with even less confusion, but with a small change to the built-in semantics, I could just redefine dofile
within the local namespace as below. I tried to avoid a change in semantics, but maybe it is acceptable since the users probably shouldn't even be using the original semantics of modifying the global namespace when they have a perfectly good local one.
dofile = myapp.import
Alternately, this change could be made in Lua itself, but of course it might (does it?) break existing code. Another option might be to allow an additional parameter specifying the namespace, e.g. dofile("hello.lua", "caller")
, but that goes a bit against the rule of thumb that the default behavior should satisfy the most common case (i.e. caller not global).
Details of Proposal: