Topic 06-modules.md
Modules
The global function dofile will evaluate a Lua file. However, it is not very useful for organizing libraries and large programs. It takes a full path to the Lua file, which is a problem for programs that need to be portable, and it will always load the source file each time.
Using require
require solves these problems by looking for the Lua file in standard locations, and only loading it once.
require is given a module name, without an extension. To understand how the modules are found, it is useful to look at the error message you get when a module is not found:
require 'alice' ---> a Linux machine lua: module 'alice' not found: no field package.preload['alice'] no file './alice.lua' no file '/usr/local/share/lua/5.1/alice.lua' no file '/usr/local/share/lua/5.1/alice/init.lua' no file './alice.so' no file '/usr/local/lib/lua/5.1/alice.so' no file '/usr/local/lib/lua/5.1/loadall.so' --> a Windows machine lua: module 'alice' not found: no field package.preload['alice'] no file '.\alice.lua' no file 'C:\Program Files\Lua\5.1\lua\alice.lua' no file 'C:\Program Files\Lua\5.1\lua\alice\init.lua' no file 'C:\Program Files\Lua\5.1\alice.lua' no file 'C:\Program Files\Lua\5.1\alice\init.lua' no file 'C:\Program Files\Lua\5.1\lua\alice.luac' no file '.\alice.dll' no file '.\alice51.dll' no file 'C:\Program Files\Lua\5.1\alice.dll' no file 'C:\Program Files\Lua\5.1\clibs\alice.dll' no file 'C:\Program Files\Lua\5.1\loadall.dll' no file 'C:\Program Files\Lua\5.1\clibs\loadall.dll'
The first place where require looks is the current directory; if there was a file
alice.lua
in the same directory as this program, it would be loaded. Then it will
look in a few standard places – for Unix this is usually the directory
/usr/local/share/lua/5.1
and for Lua for Windows it is the lua
subdirectory
of the installation directory.
Then things get interesting; it starts looking for
.so
files on Unix and .dll
files on Windows – these are binary Lua extensions
which are shared libraries, usually written in C. So require will load both pure
Lua and binary modules.
How does Lua know which locations to search? The system variable package.path contains the locations where Lua modules will be found. it is a string containing patterns separated by semi-colons: (I've printed these patterns on separate lines for clarity)
print(package.path) --> ./?.lua; /usr/local/share/lua/5.1/?.lua; /usr/local/share/lua/5.1/?/init.lua;
The procedure to find module alice
is simple; take each of these patterns, and
replace ?
with ‘alice’; if the result is an existing file, load it.
(Remember that Lua has no built-in concept of a file system; this search is done by string substitution followed by an attempt to open the result.)
If this search fails, then Lua will use package.cpath to find a binary extension in a similar way. So you can see that the error message is detailing exactly what happens in this process.
So, to summarize, require :
- takes a module name, not a file name
- looks for both Lua files and shared libraries (binary extensions)
- only loads the module once
- looks on the Lua and extension paths
A simple way to try this out is to create a Lua file mod1.lua
:
-- mod1.lua print("hello")
and require it from usemod1.lua
, in the same directory:
-- usemod1.lua require("mod1") require("mod1") print("dolly") --> hello dolly
Which shows that the file loaded by require can be any Lua code, loaded just once.
Modules
Actually, ‘module’ is just a word we use to describe Lua files that are generally useful – there is no formal concept of ‘module’ in the language itself.
Modules are usually used to make functions and data available to a program. It is better to put these into their own table:
-- mod2.lua mod2 = {} mod2.answer = function() return 42 end -- usemod2.lua require("mod2") print(mod2.answer()) --> 42
Now, after require("mod2")
our code can call mod2.answer()
. There can now be
a number of functions called answer
in the program and they will not interfere
with each other. Note how simple this system is; there is no separate data type for modules,
they are just tables.
If you move mod2.lua
to a location on your Lua path (such as
‘/usr/local/share/lua/5.1/’) then a Lua program anywhere on the system can load
the module mod2
.
Of course, to copy files into the system-wide directory often requires superuser privileges. These standard directories are built into Lua and may not be convenient for your purposes.
You can add other directories to the Lua module path by setting the
environment variable LUA_PATH
. For a Bash shell on Unix this would look like:
export LUA_PATH=";;/home/steve/lualibs/?.lua"
On Windows:
set LUA_PATH=;;c:\lua\lualibs\?.lua
Please note that the semi-colon is used to separate patterns on all systems. The double semicolon at the start means “append this to the existing Lua module path” so Lua will first look in the system-wide directory for modules.
So, there is nothing special about a Lua file loaded by require . Generally, it should create a table containing the functions. A common pattern looks like this:
-- mod3.lua local mod3 = {} function mod3.fun1() return 42 end function mod3.fun2() return mod3.fun1() end return mod3
Note that it returns the table. A user of the module may now say:
local mod3 = require 'mod3'
This way of writing modules does not create a global table. Consider the effect of
leaving out the local
when declaring mod3
: then the table is available globally.
You can then use it like follows:
require 'mod3' print(mod3.fun1())
It’s always a good idea to return the value of a module. If you do not, then
require simply returns true
, which is not very useful. Lua programmers expect
require to return a table containing the functions.
Please note that functions in a module may depend on each other, but they must reference them using the table explicitly.
module()
Using global tables of functions is going out of fashion in the Lua world, because it leads to the problems discussed in the section on variables and scope. Particularly in a big program, the aim is to keep the number of globals floating around to the absolute minimum.
There is a common style introduced in Lua 5.1 for creating modules, which many libraries use. The module function creates a named table of functions and sets the environment of the file so that these functions may be declared and without explicit reference to the table:
-- mod4.lua module("mod4") function fun1() return 42 end function fun2() return fun1() end
This has the same affect as mod3
without the local
declaration; require returns
the table, and a global variable mod4
is created which refers to the table.
It is convenient that the module functions can call each other directly, but there is a tricky little issue:
-- mod5.lua module("mod5") function dump(msg) print(msg) end
Calling mod5.dump
leads to a run-time error:
.\mod5.lua:5: attempt to call global 'print' (a nil value) stack traceback: .\mod5.lua:5: in function 'dump' ...
This is because we are not inside the global environment, but inside the environment created by module . The recommended fix is to insert the following line before the call to module :
local print = print
The other fix is to make the module call look like this:
module("mod5",package.seeall)
This makes all the global functions available to the module. It’s beter however to define what you need explicitly at the top of the module, since then readers can see at a glance what the dependencies are. (Last, but not least, using locals is significantly faster.)
Generally, we would advise you to use the ‘no magic’ style used in mod3.lua
; no globals are
harmed, and such code will work perfectly on Lua 5.1, 5.2 and LuaJIT.