rxi / lume

Lua functions geared towards gamedev
MIT License
995 stars 80 forks source link

hotswap discards non-table values #18

Open notwa opened 7 years ago

notwa commented 7 years ago

https://github.com/rxi/lume/blob/da0d1bb/lume.lua#L694-L695

    local newmod = require(modname)
    if type(oldmod) == "table" then update(oldmod, newmod) end

currently, if the returned value of a module isn't a table, it (newmod) is discarded.

in my case, my module returns a function, and i expect package.loaded to contain the new value. i am using lurker.lua to trigger hotswapping.

local some_state = 'blah'
local function exec_stuff(name)
  local f = require('stuff_'..name) -- bug: never returns new function value
  some_state = f(some_state)
end

this dirty hack seems to work:

-    if type(oldmod) == "table" then update(oldmod, newmod) end
+    if type(oldmod) == "table" then update(oldmod, newmod) else oldmod = newmod end
Alloyed commented 7 years ago

The problem here is that there's no way to modify existing functions: if you've required and stored the same function somewhere else in the past, that version doesn't get updated with your patch, which means hotswap doesn't actually hotswap anything in that case.

A workaround could be to use __call like so:

local function drop_args(n, f) return function(...) return f(select(n, ...)) end end
return setmetatable({}, {__call = drop_args(1, my_function)})

This is a normal, modifiable table object, so it should work with hotswap, but you can call it as if it were a normal function. That said, if the current behavior is fine with you you can do the same thing manually, without modifying hotswap:

package.loaded[my_mod] = nil
local f = require(my_mod)
notwa commented 7 years ago

right, afaik you can only emulate updating existing references either by utilizing a wrapper table or by replacing all of an existing table's values. that's why, in my example code, i'm running require each time a function is needed instead of caching it locally. i was expecting this.

what i'm really trying to describe is that i figured hotswap would update non-table return values in package.loaded. this includes returned numeric and userdata values as well.

nulling out the key in package.loaded would work, but that would need to be part of a lurker.lua hook to prevent reloading an untouched file, which might be expensive if the value is needed frequently.