--[[ 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