function FunctionUtils.memoize(Y,w)assert(type(Y)=="\102\117\110\099\116\105\111\110")w=w or FunctionUtils.defaultSerializeArgs assert(type(w)=="\102\117\110\099\116\105\111\110")local s={}local M=function(...)local M={...}local x=w(M)if x==nil then return Y(...)else if s[x]==nil then s[x]=Y(...)end return s[x]end end return M end function FunctionUtils.setTimeout(Y,w)local s=false local M delay(w,function()if not s then Y(M)end end)M={clear=function()s=true end}return M end function FunctionUtils.setInterval(Y,w)local s local M M=function()s=FunctionUtils.setTimeout(function()M()Y(s)end,w)end M()return{clear=function()s:clear()end}end
--[[
	Cache results of a function such that subsequent calls return the cached result rather than
	call the function again.

	By default, a cached result is stored for each separate combination of serialized input args.
	Optionally memoize takes a serializeArgs function which should return a key that the result
	should be cached with for a given call signature. Return nil to avoid caching the result.
]]
function FunctionUtils.memoize(fn, serializeArgs)
	assert(type(fn) == "function")
	serializeArgs = serializeArgs or FunctionUtils.defaultSerializeArgs
	assert(type(serializeArgs) == "function")
	local cache = {}
	local proxyFunction = function(...)
		local proxyArgs = { ... }
		local cacheKey = serializeArgs(proxyArgs)
		if cacheKey == nil then
			return fn(...)
		else
			if cache[cacheKey] == nil then
				cache[cacheKey] = fn(...)
			end
			return cache[cacheKey]
		end
	end
	return proxyFunction
end

function FunctionUtils.setTimeout(fn, secondsDelay)
	local cleared = false
	local timeout
	delay(secondsDelay, function()
		if not cleared then
			fn(timeout)
		end
	end)
	timeout = {
		clear = function()
			cleared = true
		end,
	}
	return timeout
end

function FunctionUtils.setInterval(fn, secondsDelay)
	local timeout
	local callTimeout
	callTimeout = function()
		timeout = FunctionUtils.setTimeout(function()
			callTimeout()
			fn(timeout)
		end, secondsDelay)
	end
	callTimeout()

	return {
		clear = function()
			timeout:clear()
		end,
	}
end
