Module:Memoize

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