--[[ Various functional programming bits and bobs Function signatures: fn.curry(func,...) :: function(...) :: any fn.map(tbl,func) :: table fn.compose(...) :: function(...) :: any fn.filter(tbl,func) :: table fn.zip(...) :: table fn.fill(arg,times) :: table fn.amalg(...) :: function(...) :: any fn.cycle(tbl) :: table fn.fold(tbl) :: function(func(T1,T2)::T) :: T fn.flatten(tbl) :: table ]] --AddCSLuaFile() local fn = {} if table.Copy == nil then function table.Copy(tbl) local ntbl = {} for k,v in pairs(tbl) do ntbl[k] = v end return ntbl end end --[[ Puts some arguments "in" a function so that it can be called with some number fewer arguments. Ex: local f = include("nightz/gamemode/utility/functional.lua") local debugprint = f.curry(print,"[DEBUG]") debugprint("Hello, world!") --Is the same as print("[DEBUG]","Hello, world!") ]] function fn.curry(func,...) local nargs = {...} return function(...) for k,v in pairs({...}) do nargs[k + #nargs] = v end func(unpack(nargs)) end end --[[ calls each function from first to last on every element of tbl, and returns a table with the function called. Ex: local f = include("nightz/gamemode/utility/functional.lua") local playerents = { Player(1), Player(2), Player(3) } local getname = function(ply) return ply:Nick() end local playernames = f.map(playerents) --playernames is now a table { "Player1_name", "Player2_name", "Player3_name" } ]] function fn.map(tbl,...) local nfuncs = {...} local ntbl = table.Copy(tbl) for i,j in pairs(nfuncs) do for k,v in pairs(tbl) do ntbl[k] = j(v) end end return ntbl end --[[ Calls a list of functions, starting with the last, going to the first, and passes the arguments as whatever was outputed from the previous function. Ex: local f = include("nightz/gamemode/utility/functional.lua") local printf = f.compose(print,string.format) printf("Thanks, I love %d",5) --Is the same as print(string.format("Thanks, I love %d", 5)) ]] function fn.compose(...) local nargs = {...} local n = #nargs local lastresult return function(...) lastresult = {...} while n > 0 do lastresult = {nargs[n](unpack(lastresult))} n = n - 1 end end end --[[ Removes elements from tbl for which func returns nil or false (returns new table). this WILL mess up order for arrays. Ex: local f = include("nightz/gamemode/utility/functional.lua") local sometable = { 1,3,4,5,5,6,7,8,9 } for k,v in pairs(sometable) do print(k,":",v) end --this will print: 1:1 2:3 3:4 4:5 5:5 6:6 7:7 8:8 9:9 local function iseven(k) return k%2 == 0 end local evens = f.filter(sometable,iseven) for k,v in pairs(evens) do print(k,":",v) end --this will print: 3:4 6:6 8:8 ]] function fn.filter(tbl,func) local ntbl = table.Copy(tbl) for k,v in pairs(ntbl) do if not func(v) then ntbl[k] = nil end end end --Takes n tables that have the same indexes, and returns a table that for every index, it's value is {tbl1[index],tbl2[index],...,tbln[index]} function fn.zip(...) local nargs = {...} local ntbl = table.Copy(nargs[1]) for k,v in pairs(ntbl) do local ttbl = {} for i,j in pairs(nargs) do ttbl[#ttbl + 1] = v[i] end ntbl[k] = ttbl end return ntbl end --Creates a table filled with number of arg function fn.fill(arg,times) local ret = {} for i = 1,times do ret[i] = arg end return ret end --Calls all functions passed in order, and returns all results for all functions called.S function fn.amalg(...) local nargs = {...} return function(...) local nret = {} for k,v in pairs(nargs) do local tret = {v(unpack({...}))} for i,j in pairs(tret) do nret[#nret + 1] = j end end return unpack(nret) end end --[[ Cycles a table infinitely Ex: local sometbl = {1,2,3} fn.cycle(sometbl) for i = 1, 100 do print(sometbl[i]) end Outputs: 1 2 3 1 2 : : : ]] function fn.cycle(tbl) local ntbl = table.Copy(tbl) local tbllen = #tbl local mt = { __index = function(self, ind) local id = (ind % tbllen) + 1 return tbl[id] end } setmetatable(ntbl,mt) return ntbl end --[[ Iterates over a table applying a function to each item Ex: local sometbl = {1,4,5,6,7,10} local add = function(a,b) return a + b end local sum = fn.fold(sometbl)(add) print(sum) Output: 33 ]] function fn.fold(tbl) return function(func) local running = tbl[1] for k = 2, #tbl do running = func(running,tbl[k]) end return running end end --[[ Returns an array-type table ]] function fn.flatten(tbl) local ret = {} for k,v in pairs(tbl) do ret[#ret + 1] = v end return ret end return fn