Documentation for this module may be created at Module:Memoize/doc
local memoize = {}
local nil_tag = {}
local function is_callable(f)
local tp = type(f)
if tp == 'function' then return true end
if tp == 'table' then
local mt = getmetatable(f)
return type(mt) == 'table' and is_callable(mt.__call)
end
return false
end
function memoize.memoize(func)
local mem = {} -- memoizing table
setmetatable(mem, {__mode = "k"}) -- make it weak
if not is_callable(func) then
error(string.format(
"Only functions and callable tables are memoizable. Received %s (a %s)",
tostring(func), type(func)))
end
return function (...) -- new version of 'f', with memoizing
local key = ...
key = key == nil and nil_tag or key
local v = rawget(mem, key)
if rawequal(v, nil_tag) then
return nil
elseif not rawequal(v, nil) then
return v
end
-- no previous result
v = func(...) -- calls original function
rawset(mem, key, rawequal(v, nil) and nil_tag or v) -- store result for reuse
return v
end
end
return memoize