- Introduction
- The quickest way to solve the issue
- Background and history
- How does it work?
- Example with pictures
Introduction [top]
The require statement is used to include modules in a script. There are various different ways to structure a module. Depending on how the module is structured you have to use the require()
statement a bit differently.
So why don’t we just stick to the standard Lua module structure? First because Lua is a very flexible language there is no “standard” module structure. Second when we started using Lua we used the common module(...,package.seeall)
syntax (which it turned out does not play well with annotations in the Translator). So we then moved on to other methods as described in Background and history below.
Tip: If you see require('mymodule')
it is just an alternative syntax for require 'mymodule'
the two perform identically and are interchangeable.
The quickest way to solve the issue [top]
There are two ways you can use the return()
statement, if one doesn’t work the other will.
require 'mymodule'
local MM = require 'mymodule' -- you can use any name for the variable
Background and history [top]
These are three commonly used Lua module structures, see Modules: Structure for more information on their advantages and disadvantages.
- Recommended best practice: Module with a local table interface with a
return
statement at the end of the module, this is the method recommended by the Lua committee - Good: Module with a global table interface, this method has now been deprecated by the Lua committee
- Do not use: Use
module(...,package.seeall)
syntax, this is an older method with definite disadvantages
Historically we started off using method 3 then 2 and finally 1. Many of our modules still use method 2. As far as I am aware there are no longer any modules with method 3. Therefore we will only address how method 2 and 3 work with require()
.
We also use a hybrid of one and two, call it method 1.5. This is where we use a global interface table and a return
statement. This is probably the most common module structure we use.
Tip: If you want to make you head hurt, there are many more ways to create modules in Lua!
How does it work? [top]
The require()
statement is actually just a function supplied with Lua. It is used to load and run your modules (basically it just runs the code in the module).
This give you two critical things:
- A
return
statement can be used at the end of the module to return a variable fromrequire()
- You can use see any global variable and functions in the module
So again how does it work? Ok let me explain…
Method 1: Module with a local table interface and a return
This method relies on using a return statement to return the “interface table” of functions at the end of the module. There are no global (public) variables or functions in the module, so the only way the functions can be accessed is through the returned interface table.
Here is how to use require with this type of module:
local MM = require 'mymodule' local fred = require 'mymodule' -- this also works because you can use any name for the local variable function main() MM.helloWorld() fred.helloWorld() end
Method 2: Module with a global table interface
This method uses a global “interface table” to expose the interfaces in the module. There is no return
statement the functions are accessed by referencing them through the interface table.
Note: The interface table must have exactly the same name as the module.
Here is how to use require with this type of module:
require 'mymodule' function main() mymodule.helloWorld() end
Method 1.5: Hybrid module with a global table interface and a return statement
This method uses a global “interface table” to expose the interfaces in the module and a return statement to return the “interface table” of functions at the end of the module. You can access the returned interface table, or through the by referencing them through the public interface table.
This allows you to use the syntax from method 1 and method 2, which means no matter how you use require
it works (basically the “lazy interface”).
Here is how to use require with this type of module:
-- Method 1 syntax works local MM = require 'mymodule' local fred = require 'mymodule' -- this also works because you can use any name for the local variable -- Method 2 syntax also works require 'mymodule' function main() MM.helloWorld() fred.helloWorld() mymodule.helloWorld() end
Example with pictures [top]
We will start with a method 1 module, change it to method 2 and then method 1.5. We will show how each one works as well the errors from common mistakes (and how to fix them).
Method 1: Module with a local table interface and a return
Here is the code from main()
using different variables, both work fine:
This is the module, notice how the interface table mymodule is local and is returned on the last line of the module:
So lets try the method 2 syntax, and it fails saying that mymodule is nil (which is as expected as nothing is returned from the module):
How to fix it?
- Revert the call in
main()
to the method 1 syntax (in the first picture above) - Make the mymodule variable global (converts it to “Method 1.5” below)
- Make the mymodule variable global and remove the
return
statement (converts it to Method 2 below)
Method 2: Module with a global table interface
Note: The interface table must have exactly the same name as the module.
Here is the code from main()
:
This is the module, notice how the interface table mymodule is global and is no longer returned on the last line of the module:
So lets try the method 1 syntax, and it fails saying that mymodule is boolean (which means that the require()
worked and returned “true” – which doesn’t help much):
An interesting thing to note is that our “method 2” call still works, which makes sense because require()
still exposes the global mymodule.
How to fix it?
- Revert the call in
main()
to the method 2 syntax (in the first picture) - Add the
return
statement on the last line of the module (converts to “Method 1.5” below) - Add the
return
statement on the last line of the module and make the mymodule variable global (converts to Method 1 above)
Method 1.5: Hybrid module with a global table interface and a return statement
This allows you to use the syntax from method 1 and method 2, which means no matter how you use require
it works (basically the “lazy interface”).
Here is the code from main(),
as you can see both methods work:
This is the module, notice how the interface table mymodule is global and also returned on the last line of the module:
How to fix it?
- Nothing to fix…
Note: While this might seem the ideal solution the method 1 is actually the best structure (as it keeps the module functions private), see Modules: Structure for more information.