lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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.

Here's Take 3. This variant distinguishes between the module (which is
a fixed table) and the environment, which acts as a 'shadow table'
that can look up missing stuff in the known globals.

local function loader(name, modpath)
 local mod, env = {}, {}
 env.module = function (name)
   env._NAME = name
   return env
 end
 setmetatable(env, {
    __index = lua_libs, -- resolve known globals
    __newindex = function (t,key,value)
        mod[key] = value -- put functions and constants into module!
        rawset(t,key,value) -- and into the shadow table
    end
 })
 local fh = assert(io.open(modpath, 'rb'))
 local source = fh:read'*a'
 fh:close()
 local ret = assert(load(source, modpath, 'bt', env))(name)
 return ret or mod
end

The cost of more correctness here is a copy of the module table which
is used as the environment of the module; also anything exported in
this scheme is a constant!  Which may or may not be a good thing;
personally I don't like modules owning variables.

Non-magic style continues to work, with a little extra lookup
overhead. For these explicit modules, the environment should generally
be empty; note a side-effect is that misspellings in modules will not
affect the global state of the program.  (An option to lock the
environment after loading could be used for more strictness)

(It is entirely possible that a variant of this was proposed by David
M at some point, but I can't find the reference)

steve d.