aboutsummaryrefslogtreecommitdiff
path: root/gamemode/utility/fn.lua
diff options
context:
space:
mode:
Diffstat (limited to 'gamemode/utility/fn.lua')
-rw-r--r--gamemode/utility/fn.lua229
1 files changed, 229 insertions, 0 deletions
diff --git a/gamemode/utility/fn.lua b/gamemode/utility/fn.lua
new file mode 100644
index 0000000..7c53150
--- /dev/null
+++ b/gamemode/utility/fn.lua
@@ -0,0 +1,229 @@
+--[[
+ 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 <times> 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