Lua’s module convention enables code sharing without forcing a complicated package system. A module is usually a file that creates a local table, adds public functions, and returns it.
1 | -- geometry/rectangle.lua |
1 | local rectangle = require("geometry.rectangle") |
What require does
For a module named geometry.rectangle, require first checks package.loaded. If it is absent, the function asks each entry in package.searchers to find a loader. Standard searchers cover preloaded modules, Lua files, and native C libraries.
Lua file lookup uses templates in package.path; C library lookup uses package.cpath. The ? in each template is replaced with the module path, normally converting dots to directory separators. Environment and build configuration may change these defaults.
After a loader succeeds, its return value is cached in package.loaded and reused by later calls. This means module top-level code normally runs once:
1 | local first = require("geometry.rectangle") |
Deleting package.loaded[name] can force a reload, but existing references still point to the old object. Hot reload therefore needs an explicit state and dependency strategy.
Names and submodules
The caller may assign any local name:
1 | local rect = require("geometry.rectangle") |
Submodules should be independent files such as geometry/rectangle.lua and geometry/circle.lua. A top-level geometry/init.lua may aggregate them if the configured search path supports that layout.
Avoid the legacy pattern of mutating globals or changing the module environment implicitly. Returning an explicit table keeps dependencies visible, supports testing, and prevents unrelated modules from colliding in the global namespace.