I want to separate my Lua file into two files: one that holds my functions and one that can call them. I have done a lot of research on this and all the resources I find do not explain this process very in depth. They typically say to use:
require "subsystem.lua"
I put this at the top of a new Lua file that is saved to the same directory and am not able to access anything.
Is there a config file I need to modify? Where is it?
The require
function looks in a series of places to find a module. The exact list of places can be extensively customized by adjusting fields in the global table package
.
The easiest way to get a sense of how many places and names it uses when looking for a module is to look at the error message produced when require
fails. For example, on my PC, Lua 5.1 says this:
C:\Users\Ross>lua Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio > require "xyzzy" stdin:1: module 'xyzzy' not found: no field package.preload['xyzzy'] no file '.\xyzzy.lua' no file 'C:\Program Files (x86)\Lua\5.1\lua\xyzzy.lua' no file 'C:\Program Files (x86)\Lua\5.1\lua\xyzzy\init.lua' no file 'C:\Program Files (x86)\Lua\5.1\xyzzy.lua' no file 'C:\Program Files (x86)\Lua\5.1\xyzzy\init.lua' no file 'C:\Program Files (x86)\Lua\5.1\lua\xyzzy.luac' no file '.\xyzzy.dll' no file '.\xyzzy51.dll' no file 'C:\Program Files (x86)\Lua\5.1\xyzzy.dll' no file 'C:\Program Files (x86)\Lua\5.1\xyzzy51.dll' no file 'C:\Program Files (x86)\Lua\5.1\clibs\xyzzy.dll' no file 'C:\Program Files (x86)\Lua\5.1\clibs\xyzzy51.dll' no file 'C:\Program Files (x86)\Lua\5.1\loadall.dll' no file 'C:\Program Files (x86)\Lua\5.1\clibs\loadall.dll' stack traceback: [C]: in function 'require' stdin:1: in main chunk [C]: ? >
After looking internally, the first "real" place it looks for xyzzy
is in the file named .\xyzzy.lua
. Then it tries a number of folders and names in the folder where lua.exe
was found. Finally, it looks for a DLL that might offer it. The list of folders it searches for a .lua
file is controlled by the string value in package.path
. (The comparable list for DLLs in is package.cpath
.) In that value, require
will replace each ?
with the module name, and then attempt to read the file. The first one to succeed is used.
(The story here is slightly more complicated; you can create "searchers" that require
will use to look in different places, and even change the order of the built-in searchers, but that is an advanced topic.)
So just putting modules in Lua files in the current directory should work just fine, and adjusting package.path
before calling require
for your own modules can cover most quirks you will encounter.
At its simplest, a module is just something that can be stored in package.loaded
. Which is what require
will do with it once it has been found, so that multiple calls to require
will only search once and always return the same value.
The traditional answer is for that "something" to be a table, usually mostly populated by functions that can be called, and occasionally having values. The math
module is a good example: it provides lots of functions like sin
and cos
, along with the useful value math.pi
and math.huge
.
Aside from being stored in a table, there is nothing special about a function in a module. Like any other function, it takes parameters and return zero or more values. The only real rule is that a module should not change or add global variables.
So a very minimal module file can be as simple as:
return {
addtwo = function(a, b) return a+b end,
subtwo = function(x) return x-2 end,
}
which if stored as example.lua
could be used like this:
local example = require "example"
print(example.addtwo(2,2)) -- 4
print(example.subtwo(42)) -- 40
Sticking all your code in a single table declaration will not fly for most real cases. It does not scale well, and it makes it difficult to clearly express the relationship among functions that share state.
-- simple modules
-- capture the name searched for by require
local NAME=...
-- table for our functions
local M = { }
-- A typical local function that is also published in the
-- module table.
local function addtwo(a,b) return a+b end
M.addtwo = addtwo
-- Shorthand form is less typing and doesn't use a local variable
function M.subtwo(x) return x-2 end
return M
Lua 5.1 included a standard function named module()
intended to be used at the top of module implementations. Its use was never required, and a consensus formed fairly quickly that it was not as helpful an idea as hoped. It has since been deprecated.
As a result, the simple skeleton I show above does not use it, and is portable to all versions of Lua since 5.1.