Lua Package Path
package.path is a list of templates that tells require where to look for a module file. Each template uses a placeholder for the module name, and dots in the name become directories.
Dots become directories and the placeholder is replaced
Dots become slashes in the file path. The template placeholder is then replaced by that path.
local name = "shop.cart"
local file = name:gsub("%." , "/")
local template = "lib/?.lua"
local expanded = template:gsub("%?", file)
print(file)
print(expanded)Requiring twice loads the module once
The loader is registered, then the module is required twice. The load count proves the loader ran once.
local loads = 0
package.preload["shop.cart"] = function()
loads = loads + 1
local M = {}
function M.total(a, b)
return a + b
end
return M
end
local first = require("shop.cart")
local second = require("shop.cart")
print(loads)
print(first.total(2, 3))
print(first == second)Several templates expand the same name differently
Two templates are tried in order. Each one expands the same module name to a different file path.
local name = "shop.cart"
local file = name:gsub("%." , "/")
for template in string.gmatch("lib/?.lua;lib/?/init.lua", "[^;]+") do
local expanded = template:gsub("%?", file)
print(expanded)
endExample
local loads = 0
package.preload["shop.cart"] = function()
loads = loads + 1
local M = {}
local prices = {apple = 2, bread = 3}
function M.bill(a, b)
return prices[a] + prices[b]
end
return M
end
local name = "shop.cart"
local file = name:gsub("%." , "/")
local template = "lib/?.lua"
local expanded = template:gsub("%?", file)
print(expanded)
local cart1 = require(name)
local cart2 = require(name)
print(loads)
print(cart1.bill("apple", "bread"))
print(cart1 == cart2)
print(package.loaded[name] == cart1)Key points
- Template list: package.path holds templates separated by semicolons, and require tries each one in order.
- Placeholder: the question mark in a template is replaced by the module name when require searches.
- Dots to directories: each dot in a module name becomes a directory separator in the file path.
- Preload table: package.preload holds loader functions keyed by module name for modules registered in code.
- Loaded cache: package.loaded holds modules already loaded, so a second require returns the same table.
- Load once: a loader function runs only on the first require, and later requires reuse the cached table.
In this example, the module name expands to a library file path, the preload loader registers the cart module, and two requires return the same cached table after a single load.
Note
at this level package.preload registers a module in the same file, so no outside file is needed.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
A module is registered in package.preload and required twice. How many times does its loader function run?