lua-users home
lua-l archive

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


On Tue, Oct 18, 2011 at 5:35 AM, David Manura <dm.lua@math2.org> wrote:
>
> Now, if one wanted to "fix" the module function, I think a solution
> roughly along the following lines might be acceptable to all parties.
> Modules could be written like this:
>

<snip foo.lua and loadmodule.lua>

Why not run with this idea and make something like your loadmodule.lua
the standard loader for Lua modules? See below:

------- loader.lua -----
-- this could be just the base lib!
local _G = package.loaded._G

-- an API function can make this pretty fast
local function clone(t)
  local nt = {}
  for k, v in pairs(t) do
    nt[k] = v
  end
  return nt
end

local function loader(name, modpath)
  local env = setmetatable({}, { __index = _G })
  env.module = function (name)
    env._NAME = name
    return env
  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 clone(env)
end

-- replace Lua loder
package.searchers[2] = function (name)
  local modpath, msg = package.searchpath(name, package.path)
  if modpath then
    return loader, modpath
  else
    return nil, msg
  end
end

------- end loader.lua -----

A simple module:

------- foo.lua -----
module "foo"

local msg = "Hello World"

function bar()
  print(msg)
end

------- end foo.lua -----

------- main.lua -----

local foo = require "foo"
foo.bar()
print(foo.print)
print(foo._NAME)

------- end main.lua -----

$ ./lua -e "dofile('loader.lua')" main.lua
Hello World
nil
foo
$

This loader loads a module in a sandbox environment (it could just
provide the Lua base library, making the module use require even for
io, os, etc.), and a shallow copy of this environment becomes the
module. This allows modules to export symbols through globals, as
current modules that use "module", but they cannot pollute the global
environment by accident, and the module table does not keep references
to Lua library functions.

If the module returns a table then the loader assumes that this table
is the module and does not clone the environment, this lets Lua 5.1
modules that do not use "module" keep working. Removing this will
break more modules, but brings more consistency among modules. An
alternate loader could even register the module in the global
environment, as module currently does (good for simple scripts, and
the REPL).

All the flexibility of the searchers/loaders/require mechanism (the
mechanisms) will be still there for anyone embedding Lua, this just
sets tighter policy for the ecosystem of standalone Lua.

--
Fabio Mascarenhas