Home
Reading
Searching
Subscribe
Sponsors
Statistics
Posting
Contact
Spam
Lists
Links
About
Hosting
Filtering
Features Download
Marketing
Archives
FAQ
Blog
 
Gmane
From: Fabio Mascarenhas <mascarenhas <at> acm.org>
Subject: Re: modules, require, magic
Newsgroups: gmane.comp.lang.lua.general
Date: Tuesday 18th October 2011 15:50:40 UTC (over 5 years ago)
On Tue, Oct 18, 2011 at 5:35 AM, David Manura  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:
>



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
 
CD: 3ms