As Nicol said, the language itself doesn't do it for you.
If you want to implement something like this yourself though, it's not that hard, the only thing "preventing" you is any "leftover" references (which will still point to the old code) and the fact require
caches its return value in package.loaded
.
The way I'd do it is by dividing your code into 3 modules:
- the reloading logic at entry point (
main.lua
)
- any data you want to preserve across reloads (
data.lua
)
- the actual code to reload (
payload.lua
), making sure you don't keep any references to that (which is sometimes not possible when you e.g. have to give callbacks to some library; see below).
-- main.lua:
local PL = require("payload")
local D = require("data")
function reload(module)
package.loaded[module]=nil -- this makes `require` forget about its cache
return require(module)
end
PL.setX(5)
PL.setY(10)
PL.printX()
PL.printY()
-- .... somehow detect you want to reload:
print "reloading"
PL = reload("payload") -- make sure you don't keep references to PL elsewhere, e.g. as a function upvalue!
PL.printX()
PL.printY()
-- data.lua:
return {} -- this is a pretty dumb module, it's literally just a table stored in `package.loaded.data` to make sure everyone gets the same instance when requiring it.
-- payload.lua:
local D = require("data")
local y = 0
return {
setX = function(nx) D.x = nx end, -- using the data module is preserved
setY = function(ny) y = ny end, -- using a local is reset upon reload
printX = function() print("x:",D.x) end,
printY = function() print("y:", y) end
}
output:
x: 5
y: 10
reloading
x: 5
y: 0
you could flesh out that logic a bit better by having a "registry module" that keeps track of all the requiring/reloading for you and abstracts away any access into modules (thus allowing you to replace the references), and, using the __index
metatable on that registry you could make it pretty much transparent without having to call ugly getters all over the place. this also means you can supply "one liner" callbacks that then actually just tail-call through the registry, if any 3rd party library needs that.