Module:Memoizer
Utility module which allows most functions to be memoized based on their arguments; the memoized function caches results for each unique set of arguments, avoiding expensive recomputations if the function is known to be pure, such as Cargo queries. The module exposes a single function, memoizer
, which accepts two arguments:
- func: The function to be memoized. It may accept any number of arguments, and it may return
nil
. It must not return more than one value (extra values are discarded) or call itself (recursive functions cannot access memoized versions of themselves). - keyfn: If provided, the memoizer calls this object using the passed arguments to construct a key for the arguments; otherwise, the first argument is used as the key. Invocations that produce the same key will return the same cached value. If the returned value is a table or userdata, it is referenced by all invocations of the same key and never duplicated.
Example[edit source]
local memoize = require 'Module:Memoizer'.memoizer
local origin = memoize(function (hero)
mw.log(hero)
local result = mw.ext.cargo.query('Units', 'Origin', {where = ("_pageName='%s'"):format(hero)})[1]
return result and result.Origin or 'Unknown'
end)
mw.log(origin('Wrys: Kindly Priest'))
-- Wrys: Kindly Priest
-- Fire Emblem: Shadow Dragon and the Blade of Light
mw.log(origin('Wrys: Kindly Priest'))
-- Fire Emblem: Shadow Dragon and the Blade of Light
mw.log(origin('Clarine: Refined Noble'))
-- Clarine: Refined Noble
-- Fire Emblem: The Binding Blade
mw.log(origin('Wrys: Kindly Priest'))
-- Fire Emblem: Shadow Dragon and the Blade of Light
mw.log(origin('Clarine: Refined Noble'))
-- Fire Emblem: The Binding Blade
mw.log(origin('INVALID'))
-- INVALID
-- Unknown
mw.log(origin('INVALID'))
-- Unknown
local sum = memoize(function (x, y)
mw.log(x .. ' + ' .. y .. ' =')
return x + y
end, function (x, y)
return math.min(x, y) .. ';' .. math.max(x, y)
end)
mw.log(sum(2, 4))
-- 2 + 4 =
-- 6
mw.log(sum(2, 3))
-- 2 + 3 =
-- 5
mw.log(sum(2, 4))
-- 6
mw.log(sum(4, 2))
-- 6
mw.log(sum(3, 3))
-- 3 + 3 =
-- 6
The above documentation is transcluded from Module:Memoizer/doc. (edit | history)
local nil_tag = {}
local memoizer = function (func, keyfn)
local cache = setmetatable({}, {__mode = 'k'})
if not keyfn then
return function (...)
local key = ...
key = key == nil and nil_tag or key
local v = rawget(cache, key)
if rawequal(v, nil_tag) then
return nil
elseif not rawequal(v, nil) then
return v
end
v = func(...)
rawset(cache, key, rawequal(v, nil) and nil_tag or v)
return v
end
end
return function (...)
local key = keyfn(...)
key = key == nil and nil_tag or key
local v = rawget(cache, key)
if rawequal(v, nil_tag) then
return nil
elseif not rawequal(v, nil) then
return v
end
v = func(...)
rawset(cache, key, rawequal(v, nil) and nil_tag or v)
return v
end
end
return {
memoizer = memoizer,
}