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