lua-users home
lua-l archive

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

On 19.10.2011 11:53, steve donovan wrote:
On Wed, Oct 19, 2011 at 11:04 AM, steve donovan
<>  wrote:
On Wed, Oct 19, 2011 at 9:09 AM, Hisham<>  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
  setmetatable(env, {
     __index = lua_libs, -- resolve known globals
  local fh = assert(, 'rb'))
  local source = fh:read'*a'
  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
  return mod

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
env._NAME = name

The 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.