lua-users home
lua-l archive

Re: modules, require, magic

[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
<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 = 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.
Philipp

AltStyle によって変換されたページ (->オリジナル) /