lua-users home
lua-l archive

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


Hi,

stukov@gala.net wrote:
> Is it posible to create nested modules using lua 5.1w6 ?

Yes, by using hierarchical module names. This is the designated
way to organize packages:

Module name          Path relative to install directory
-------------------------------------------------------
packageA.init        packageA/init.lua
packageA.module1     packageA/module1.lua
packageA.module2     packageA/module2.lua

packageB.init        packageB/init.lua
packageB.module1     packageB/module1.lua
packageB.module2     packageB/module2.lua

* You can just use
  require "packageA"
to load package A, because package.path has both ?.lua
and ?/init.lua (relative to the install directory).

Note: this particular feature only works relative to the
install directory, but not relative to the current directory.
Have a look at the full path with:
  lua -e 'print(package.path)'

* From inside a package you can load the other modules
of the same package by giving the full module name:
  require "packageA.module1"

Note: At least from */init.lua you _have_ to use the full
syntax. This is because 'module "packageA"' cannot know that
this is the name of a package (and not a plain module) and
that the name should be split differently.

* From within other modules inside a package you can use
relative syntax (but you have to put module(...) before that):
  local module2 = require(_PACKAGE.."module2")

Submodules with the same names in different packages do not
conflict because their module tables are stored in a different
hierarchy (under a global + subtables with the same name as
the submodule name).

Example:

--Application:
require "foo"
require "bar"
print(foo.xyz.var)
print(bar.xyz.var)


--foo/init.lua
module "foo"
require "foo.xyz"

--foo/xyz.lua
module(...)
var = "set by foo.xyz"


--bar/init.lua
module "bar"
require "bar.xyz"

--bar/xyz.lua
module(...)
var = "set by bar.xyz"


Here are a few recommendations/tips:

* Use the following syntax to get convenient access to modules
and/or submodules:
  local foo = require "foo"
  local bar = require "abc.def.ghi.bar"
This caches the module table in a local variable (it's faster, too).

* The package initializer should load the other submodules, but
add only minimum functionality itself. The package initializer
should use an explicit name for module(), i.e. module("foo")
and _not_ module(...) (because it may be loaded under two
different names).

* Package submodules that depend on functionality from other
package submodules should explicitly require the other submodules:
  local module2 = require(_PACKAGE.."module2")
... just in case the submodule is loaded independently from
the package.

* Package submodules that cannot be loaded independently should
require the package initializer first:
  module(...)
  local package = require(_PACKAGE.."init")
This works fine, because the module system can handle circular
dependencies. But be careful when you cache elements from module
tables in locals -- caching the module table itself is ok.

* Yes, you can use deep nesting, e.g.: module "foo.bar.baz"
The module system treats everything up to the last dot as the
package name (_PACKAGE = "foo.bar.") and everything after that
as the submodule name (_NAME = "baz").

* If you require explicit access to your own (sub)module table,
use _M. Newly created globals (e.g. global function definitions)
are implicitly stored there (var=1 is the same as _M.var=1).

Bye,
     Mike