How does module() work?

module is used to create a module that can then be require d. Although not compulsory, it simplifies the creation of standard Lua modules.

-- testm.lua (somewhere on the Lua path)
local print = print module ("testm")
function export1(s)
 print(s)
end function export2(s)
 export1(s)
end

After require ("testm") you can then call the exported functions as testm.export2("text") etc. So the first thing module does is create a table for your new functions; it also ensures that require will return this table (rather than just true)

Second, it sets the function environment of the chunk to be this table. This in effect makes it work like a 'namespace' in other languages; within the module testm, any function can see all other functions directly without qualifying with testm. This means that any global functions are not visible by default, which is why we had to create a local alias to print.

People can find this restrictive, so often modules are declared like so:

module ("testm",package.seeall)

This modifies the module table so that any unsatisfied look-up is done globally, so that the local declaration of print becomes unnecessary. (This is done by giving the table a metatable with __index pointing to the global table _G); note that accessing globals like this will be slower than explicitly declaring them as locals.

It is possible to write module (...) at the start of your module. When loaded, the module will be called with the name of the module as determined by require. This means that the module itself does not contain its name, and can be freely moved around.

The essential meaning of module is contained in this code snippet:

function mod(name)
 module ('test',package.seeall)
 function export()
 print 'export!'
 end end mod('test')
test.export()

That is, the module call makes the environment of the function mod to be test, so that any functions defined inside it are actually inside the test table.

1.37.1 Criticism of module()

The first criticism is that package.seeall exposes the global table in cases where you really want to restrict access to functionality. It results in 'leaky encapsulation' which makes it easy for any user of this module to access global functions or tables through the module itself, e.g. testm.io.

The second criticism is that a module using module creates global tables and exports its dependencies. module "hello.world" creates a table hello (if not already present) and world as a table within that. If hello.world requires fred then fred becomes automatically available to all users of hello.world, who may come to depend on this implementation detail and get confused if it changed.

See here.

Please note that module() has been deprecated for Lua 5.2; developers are encouraged to use a simple no-magic style for writing modules.

1.37.2 Life after module()?

This module style remains portable between Lua 5.1 and Lua 5.2, where every exported function is explicitly put into a module table:

-- mod.lua local M = {}
function M.answer()
 return 42
end function M.show()
 print(M.answer())
end return M

Note that no globals are created and in fact no module names are specified. So you need to assign the module to a variable before use:

local mod = require 'mod'

The disadvantage of the 'no-magic' style is that every module function reference has to be qualified, which can be a problem when converting code using module(). This alternative declares the functions up front:

local answer, show function answer() return 42 end function show() print(answer()) end return {answer=answer,show=show}

This also has the advantage that (a) exported functions are explicitly mentioned at the end and (b) all function accesses are local and hence faster. (Modules with a lot of functions will hit the local limit of about 240, but this is probably an excessive case.)



Back