lua-users home
lua-l archive

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


On 16 April 2013 11:35, Hisham <h@hisham.hm> wrote:
> That's why what I always wanted from the module system, instead of the
> wild-west of package.seeall, was a way to get a guaranteed "reset"
> environment (like a 'package.seebase' of sorts) with only the standard
> Lua globals. If Lua can construct a default environment for the main
> chunk and populate the standard libraries there, I figure it could
> just as well do the same for modules, to ensure that module authors
> can work with a stable set of assumptions about the environment, just
> like script writers do.

To put it a bit more formally, I guess the behavior I'd like is this:

-- HHM_module.lua ------------------------------
local standard_libraries = {}

for k,v in pairs(_G) do
   standard_libraries[k] = v
end

function module(name, ...)
   local mod = package.loaded[assert(name)]
   if type(mod) ~= "table" then
     mod = {}
     mod._M = mod
     mod._NAME = name
     mod._PACKAGE = name:sub(1, name:len() - (name:reverse():find(".",
1, true) or 0))
     setmetatable(mod, { __index = standard_libraries })
     local modproxy = {}
     setmetatable(modproxy, { __index = function(t, k) return
rawget(mod, k) end })
     package.loaded[name] = modproxy
     for i = 1, select("#", ...) do
        select(i, ...)(mod)
     end
   end
   return mod
end

standard_libraries.module = module
----------------------------------------

-- mymod.lua ------------------------------

-- Creating a random global for demonstration purposes
dirty_env = "yes"

local _ENV = module("argh")

-- The environment is clean!
assert(not dirty_env)

function groo()
   -- The standard library is available!
   print("Groo!")
end

local _ENV = module("mymod")

-- Messing locally with standard globals
local original_print = print
function print(...)
   original_print("***", ..., "***")
end

function blo()
   -- This prints with asterisks
   print("I'm Blo!")
end
----------------------------------------

-- main.lua ------------------------------
local mymod = require("mymod")
local argh = require("argh")

mymod.blo()

argh.print = function()
   print("trying to mess with argh's print!")
   -- This won't succeed
end
-- argh.groo() still uses the standard print
argh.groo()

-- Even though they're in the same file,
-- blo did not leak into the argh module
assert(not pcall(argh.blo))
----------------------------------------

]/Programs/Lua/5.2.0/bin/lua -lHHM_module main.lua
***	I'm Blo!	***
Groo!

-- Hisham
http://hisham.hm/