Lua Module Loader
What if I told you there is a way to extend the default syntax of Lua? In the below example I use @
as an alias for self
, and fn
as an alias of function
. This and may more can be achived with the module loader in Lua
-- myfile.lua
local greet = fn(name)
print('Hello ' .. name)
end
greet('mark1626')
---
-- cube.lua
Cube = {a = 1}
function Cube:new(o)
o = o or {}
setmetatable(o, @)
@.__index = @
return o
end
function Cube:area()
return @.a * @.a
end
return Cube
Module Loader
The package loaders is a table used by require to load modules. This can be overridden with a simple table.insert
to add our custom logic
In the below I implement a custom loader that runs a function transform
over the contents of the file
local custom_loader = function(modulename)
local modulepath = string.gsub(modulename, "%.", "/")
for path in string.gmatch(package.path, "([^;]+)") do
local filename = string.gsub(path, "%?", modulepath)
local file = io.open(filename, "rb")
if file then
local content = assert(file:read("*a"))
local transformed_file = transform(content)
return assert(loadstring(transformed_file, modulename))
end
end
return "Unable to load file " .. modulename
end
-- Override the default loader
table.insert(package.loaders, 2, custom_loader)
Note: This will work on all the future require after importing this module Note: In Lua 5.3 this is called package searchers
Transformation Use Case
Now let’s have a look at the first example I posted
local greet = fn(name)
print('Hello ' .. name)
end
This is the transform function I use to achieve this uses a simple string replace. fn(
is converted into function(
-- This will transform some patterns in our file
local function transform(s)
local str = s
local int = "([%d]+)"
local patterns = {
{ patt = "@", repl = "self" },
{ patt = "&&", repl = " and " },
{ patt = "||", repl = " or " },
{ patt = "fn%(", repl = "function(" },
}
for _, v in ipairs(patterns) do str = str:gsub(v.patt, v.repl) end
return str
end