The require Function
require("modname") is Lua's standard mechanism for loading external code. It searches package.path (a semicolon-separated list of file path templates using ? as a placeholder for the module name) for a matching .lua file, runs that file exactly once, caches its return value in package.loaded[modname], and returns that value on every subsequent require call for the same name. This caching means a module's top-level code executes only once per program run, no matter how many files require it.
Cricket analogy: A commentary panel only needs to fetch a player's official bio from the ICC database once per broadcast, then reuses the cached data for every mention afterward, mirroring how require() caches a module after the first load.
-- File: mathutils.lua
local M = {}
function M.square(x)
return x * x
end
function M.clamp(x, lo, hi)
if x < lo then return lo end
if x > hi then return hi end
return x
end
return M
-- File: main.lua
local mathutils = require("mathutils")
print(mathutils.square(5)) --> 25
print(mathutils.clamp(15, 0, 10)) --> 10The Return-a-Table Convention
The idiomatic Lua module pattern is to declare a local table (commonly named M or the module name itself) at the top of the file, attach every public function and constant to it as the file progresses, and finish with return M. Anything declared local and not attached to that table stays private to the module, effectively giving you file-level encapsulation, since require only exposes whatever value the file explicitly returns.
Cricket analogy: A franchise only reveals its final playing XI on the team sheet handed to the umpire, keeping net-session experiments private, the way a module only exposes what's attached to the returned table.
package.path and Search Locations
package.path holds the templates Lua uses to locate .lua files, such as ./?.lua;./?/init.lua;/usr/local/share/lua/5.4/?.lua, where each ? is replaced with the dotted module name (dots become path separators). package.cpath serves the same purpose for compiled C libraries (.so/.dll). You can prepend project-specific directories by modifying package.path at the top of your entry script, which is the common way to make require("mymodule") find files inside a custom lib/ folder.
Cricket analogy: A scout checks a shortlist of specific regional academies in a fixed order when looking for a promising player, similar to how require() checks each template in package.path in sequence.
require uses dots in the module name as a hint for nested paths only by convention in some path templates (e.g. require("mypkg.util") looking for mypkg/util.lua), but it does NOT automatically convert dots to slashes unless your package.path templates are written to do so — always verify your path templates match your actual directory layout.
require("name")loads a.luafile found viapackage.path, executes it once, and caches the result inpackage.loaded.- Subsequent
requirecalls for the same module name return the cached value instantly without re-running the file. - The idiomatic module pattern builds a local table, attaches public functions to it, and ends with
return M. - Locals not attached to the returned table are private to the module file, providing simple encapsulation.
package.pathis a semicolon-separated list of?-templated search paths;package.cpathdoes the same for C libraries.- You can prepend custom directories to
package.pathat program startup to support project-specificlib/folders.
Practice what you learned
1. What happens the second time you call `require("mathutils")` in the same program?
2. In the idiomatic module pattern, how do you make a helper function private to a module?
3. What does `?` represent in a package.path template like `./?.lua`?
4. What is package.cpath used for?
Was this page helpful?
You May Also Like
Object-Oriented Lua
Learn how Lua uses tables, functions, and metatables to build objects, methods, and encapsulation without a built-in class system.
Error Handling in Lua (pcall/error)
Learn how Lua signals and catches errors using error(), pcall(), and xpcall(), instead of try/catch exceptions.
Coroutines in Lua
Understand Lua's cooperative multitasking primitive: creating, resuming, and yielding coroutines to write generators and non-blocking logic.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics