lua-users home
lua-l archive

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



On 6-Mar-07, at 12:17 PM, Norman Ramsey wrote:

I'm building a fairly large package consisting of a mix of C code and
Lua code.  Following previous advice I've made the C code a submodule,
which is working well. But this is going to be a large package (probably
2000-3000 lines of Lua code), and while there are several well-defined
submodules in the package, some of the submodules (such as the module
containing all the package-specific commands intended for clients) are
too large to put in one file.  So, I would like to have multiple
files, each loaded with 'require', that all contribute to the same
submodule.

Does anyone have advice about sensible ways to do this?
(I have several ideas but feel I am treading on thin ice...)


You can feel free to ignore this advice, as it is just
my way, and quite possibly doesn't reflect the philosophy
of the module system since the modules I write generally
don't install themselves into the global environment, and
don't use package.seeall() to avoid typing the module name.

Anyway, this is how I do it: (with some notes at the bottom)

-------------------------------
-- file lualib/bigmodule.lua
-- At a minimum, contains:
--   return {}
-- But it's usually more like this:

local module = {}
function module.basic(x)
  --
end

function module.morebasic(x, y)
  --
end

return module

------------------------------------
-- file lualib/bigmodule/sub_a.lua
-- magic line to get the containing module
local module = require((...):match"(.*)%.")

function module.a(x)
  --
end

return module

---------------------------------
-- file lualib/bigmodule/sub_b.lua
local module = require((...):match"(.*)%.")

function module.b(x)
  --
end

return module

---- etcetera
------------------------------------

Notes:
------

1. There's no requirement that the submodules actually be in the
same directory structure as each other, or the main module; they
just have to be in a similar path from some root in LUA_PATH. That
can be handy if you want to put the core definitions in, say,
  /usr/local/lualib/bigmodule
and have some user extension in, say,
  /home/you/lualib/bigmodule/extension.lua


2. Sometimes, one submodule requires another submodule. The following
function is handy (partly to get around the magic invocation above):

function family(me, ...)
  local mom = me:match"(.*)%."
  for _, sis in ipairs{...} do require(mom.."."..sis) end
  return require(mom)
end

Then you can start a module with:

local module = family(..., "sub_a", "sub_b")

3. While not polluting the global namespace is nice in
production code, it can be annoying for casual shell sessions
or debugging. So the following module (modules.lua, or whatever)
can be useful:

--- file modules.lua
-- For times when we'd prefer a module, but don't require it
function prefer(modname)
  local ok, mod = pcall(require, modname)
  return ok and mod, mod
end

-- Lots of details omitted; the real version tries harder to
-- generate error messages if the module exists but has compile
-- errors
setmetatable(_G, {__index = function(_, k) return prefer(k) end})
return true

--- Then start lua with the command lua -lmodules

That has the possibly unexpected consequence that you can set the
lua command prompt by creating a file called _PROMPT.lua with
the contents:

  return "<some string>"