function FunctionUtils.memoize(b,w)assert(type(b)=="\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 H={}local V=function(...)local V={...}local P=w(V)if P==nil then return b(...)else if H[P]==nil then H[P]=b(...)end return H[P]end end return V end function FunctionUtils.setTimeout(b,w)local H=false local V delay(w,function()if not H then b(V)end end)V={clear=function()H=true end}return V end function FunctionUtils.setInterval(b,w)local H local V V=function()H=FunctionUtils.setTimeout(function()V()b(H)end,w)end V()return{clear=function()H:clear()end}end

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
