Memoize Function
This commit is contained in:
parent
3c8c64c6bf
commit
d33951b713
1 changed files with 68 additions and 0 deletions
68
ModuleScripts/Memoize.lua
Normal file
68
ModuleScripts/Memoize.lua
Normal file
|
@ -0,0 +1,68 @@
|
|||
--[[
|
||||
memoize creates a function as a wrapper that caches the last outputs of a function.
|
||||
This is useful if you know that the function should return the same output every
|
||||
time it is run with the same inputs. The function should only return an output, and
|
||||
not have any side effects. These side effects are not cached.
|
||||
|
||||
Without memoize's caching, even though the function ouputs the same values, the
|
||||
memory locations of the values are different; tables made in the function, even if
|
||||
they have the same values, won't be the same tables.
|
||||
|
||||
memoize only caches the last set of inputs and ouputs. This means that it is only
|
||||
helpful when the function is likely to be called with the same inputs multiple
|
||||
times in a row. This is the case with most Roact use cases.
|
||||
|
||||
Note that memoize only does a ** shallow check on table inputs ** . This means
|
||||
that if the same table is input but the elements of the table are different then
|
||||
it will be assumed that the table has not changed.
|
||||
|
||||
In addition to all the previous warnings, memoize strips trailing nils. This means
|
||||
that if foo is a memoized function and we call foo(), then foo(nil) will return a
|
||||
cached value. This is opposed to how print handles input. print() only outputs a
|
||||
new line, but print(nil) outputs "nil". This is because varargs can detect the
|
||||
number of arguments passed in. So, be careful when using memoize with varargs.
|
||||
Trailing nils will be stripped.
|
||||
|
||||
The wrapper can take any number of inputs and give any number of outputs.
|
||||
Leading and interspersed nils are handled gracefully. Trailing nils on the input
|
||||
are stripped.
|
||||
]]
|
||||
local function captureSize(...)
|
||||
return {...}, select("#", ...)
|
||||
end
|
||||
|
||||
local function memoize(func)
|
||||
assert(type(func) == "function", "memoize requires a function to memoize")
|
||||
|
||||
local lastArgs
|
||||
local lastNumArgs
|
||||
local lastOutput
|
||||
local lastNumOutput
|
||||
|
||||
return function(...)
|
||||
local numArgs = select("#", ...)
|
||||
|
||||
while numArgs > 0 and select(numArgs, ...) == nil do
|
||||
numArgs = numArgs - 1
|
||||
end
|
||||
|
||||
if numArgs ~= lastNumArgs then
|
||||
lastArgs = {...}
|
||||
lastNumArgs = numArgs
|
||||
lastOutput, lastNumOutput = captureSize(func(...))
|
||||
return unpack(lastOutput, 1, lastNumOutput)
|
||||
end
|
||||
|
||||
for i = 1, lastNumArgs do
|
||||
if select(i, ...) ~= lastArgs[i] then
|
||||
lastArgs = {...}
|
||||
lastOutput, lastNumOutput = captureSize(func(...))
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return unpack(lastOutput, 1, lastNumOutput)
|
||||
end
|
||||
end
|
||||
|
||||
return memoize
|
Loading…
Reference in a new issue