The Alchemist Code Wiki

READ MORE

The Alchemist Code Wiki
Advertisement

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
Advertisement