|
On 19.10.2011 11:53, steve donovan wrote:
On Wed, Oct 19, 2011 at 11:04 AM, steve donovan <steve.j.donovan@gmail.com> wrote:On Wed, Oct 19, 2011 at 9:09 AM, Hisham<hisham.hm@gmail.com> wrote:and your example shows how that can be a problem. Take 2, then: I believe the following addresses this issue, and I couldn't spot any side effects.Take 4 should be easier to understand: local function loader(name, modpath) local env = {} env.module = function (name) env._NAME = name return env end setmetatable(env, { __index = lua_libs, -- resolve known globals }) local fh = assert(io.open(modpath, 'rb')) local source = fh:read'*a' fh:close() local ret = assert(load(source, modpath, 'bt', env))(name) if ret then return ret end -- explicit table was returned local mod = {} -- the module is a copy of the environment after initial loading for k,v in pairs(env) do mod[k] = v end return mod end Very little metamagic left, except the old trick used by package.seeall. Here it's more explicit that what we call the module is actually a copy of the environment used when loading modules.
Looks acceptable to me if you replace env.module = function (name) ... end with env._NAME = nameThe module already has a name, it is passed to require and the loader function. There is no need for a second name (any more). Even when the second name (the "module-name" as opposed to the "require-name") was used to define the name of the exported globals it just presented two opportunities for name clashes instead of one and possibly serious name confusion if "require-name" and the names of the globals differed. Without an explicit second "module-name" there is no reason to keep module either. I like about this proposal, that you cannot (accidentally or intentionally) define globals, but, as I wrote elsewhere, I'm not sure you should in general ban this from all require'd Lua code.
I still wouldn't use the "module is environment copy" feature, because - sometimes I return non-tables from modules (typically functions)- almost all of my modules have a __call-metamethod (for constructors or for returning a 'properly configured' module table) and some also an __index-metamethod (for inheritance)
- exported functions can't be confused with predeclared local functions. Philipp