dobrograd-13-06-2022/garrysmod/gamemodes/darkrp/gamemode/libraries/fn.lua
Jonny_Bro (Nikita) e4d5311906 first commit
2023-11-16 15:01:19 +05:00

337 lines
7 KiB
Lua

/*---------------------------------------------------------------------------
Functional library
by FPtje Atheos
---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
Function currying
Take a function with n parameters.
Currying is the procedure of storing k < n parameters "in the function"
in such a way that the remaining function can be called with n - k parameters
Example:
DebugPrint = fp{print, "[DEBUG]"}
DebugPrint("TEST")
> [DEBUG] TEST
---------------------------------------------------------------------------*/
function fp(tbl)
local func = tbl[1]
return function(...)
local fnArgs = {}
local arg = {...}
local tblN = table.maxn(tbl)
for i = 2, tblN do fnArgs[i - 1] = tbl[i] end
for i = 1, table.maxn(arg) do fnArgs[tblN + i - 1] = arg[i] end
return func(unpack(fnArgs, 1, table.maxn(fnArgs)))
end
end
local unpack = unpack
local table = table
local pairs = pairs
local ipairs = ipairs
local error = error
local math = math
local select = select
local type = type
local _G = _G
local fp = fp
module("fn")
/*---------------------------------------------------------------------------
Parameter manipulation
---------------------------------------------------------------------------*/
Id = function(...) return ... end
Flip = function(f)
if not f then error("not a function") end
return function(b, a, ...)
return f(a, b, ...)
end
end
-- Definition from http://lua-users.org/wiki/CurriedLua
ReverseArgs = function(...)
--reverse args by building a function to do it, similar to the unpack() example
local function reverse_h(acc, v, ...)
if select('#', ...) == 0 then
return v, acc()
else
return reverse_h(function () return v, acc() end, ...)
end
end
-- initial acc is the end of the list
return reverse_h(function () return end, ...)
end
/*---------------------------------------------------------------------------
Misc functions
---------------------------------------------------------------------------*/
-- function composition
-- function composition
do
local function comp_h(a, b, ...)
if b == nil then return a end
b = comp_h(b, ...)
return function(...)
return a(b(...))
end
end
Compose = function(funcs, ...)
if type(funcs) == 'table' then
return comp_h(unpack(funcs))
else
return comp_h(funcs, ...)
end
end
end
_G.fc = Compose
-- Definition from http://lua-users.org/wiki/CurriedLua
Curry = function(func, num_args)
if not num_args then error("Missing argument #2: num_args") end
if not func then error("Function does not exist!", 2) end
-- helper
local function curry_h(argtrace, n)
if n == 0 then
-- reverse argument list and call function
return func(ReverseArgs(argtrace()))
else
-- "push" argument (by building a wrapper function) and decrement n
return function(x)
return curry_h(function() return x, argtrace() end, n - 1)
end
end
end
-- no sense currying for 1 arg or less
if num_args > 1 then
return curry_h(function() return end, num_args)
else
return func
end
end
-- Thanks Lexic!
Partial = function(func, ...)
local args = {...}
return function(...)
return func(unpack(table.Add( args, {...})))
end
end
Apply = function(f, ...) return f(...) end
Const = function(a, b) return a end
Until = function(cmp, fn, val)
if cmp(val) then
return val
end
return Until(cmp, fn, fn(val))
end
Seq = function(f, x) f(x) return x end
GetGlobalVar = function(key) return _G[key] end
/*---------------------------------------------------------------------------
Mathematical operators and functions
---------------------------------------------------------------------------*/
Add = function(a, b) return a + b end
Sub = function(a, b) return a - b end
Mul = function(a, b) return a * b end
Div = function(a, b) return a / b end
Mod = function(a, b) return a % b end
Neg = function(a) return -a end
Eq = function(a, b) return a == b end
Neq = function(a, b) return a ~= b end
Gt = function(a, b) return a > b end
Lt = function(a, b) return a < b end
Gte = function(a, b) return a >= b end
Lte = function(a, b) return a <= b end
Succ = Compose{Add, 1}
Pred = Compose{Flip(Sub), 1}
Even = Compose{fp{Eq, 0}, fp{Flip(Mod), 2}}
Odd = Compose{Not, Even}
/*---------------------------------------------------------------------------
Functional logical operators and conditions
---------------------------------------------------------------------------*/
FAnd = function(fns)
return function(...)
local val
for _, f in pairs(fns) do
val = {f(...)}
if not val[1] then return unpack(val) end
end
if val then return unpack(val) end
end
end
FOr = function(fns)
return function(...)
for _, f in pairs(fns) do
local val = {f(...)}
if val[1] then return unpack(val) end
end
return false
end
end
Not = function(x) return not x end
If = function(f, Then, Else)
return function(x)
if f(x) then
return Then
else
return Else
end
end
end
/*---------------------------------------------------------------------------
List operations
---------------------------------------------------------------------------*/
Map = function(f, xs)
for k, v in pairs(xs) do
xs[k] = f(v)
end
return xs
end
Append = function(xs, ys)
return table.Add(xs, ys)
end
Filter = function(f, xs)
local res = {}
for k,v in pairs(xs) do
if f(v) then res[k] = v end
end
return res
end
ForEach = function(f, xs)
for k,v in pairs(xs) do
local val = f(k, v)
if val ~= nil then return val end
end
end
Head = function(xs)
return table.GetFirstValue(xs)
end
Last = function(xs)
return xs[#xs] or table.GetLastValue(xs)
end
Tail = function(xs)
table.remove(xs, 1)
return xs
end
Init = function(xs)
xs[#xs] = nil
return xs
end
GetValue = function(i, xs)
return xs[i]
end
Null = function(xs)
for k, v in pairs(xs) do
return false
end
return true
end
Length = function(xs)
return #xs
end
Index = function(xs, i)
return xs[i]
end
Reverse = function(xs)
local res = {}
for i = #xs, 1, -1 do
res[#xs - i + 1] = xs[i]
end
return res
end
/*---------------------------------------------------------------------------
Folds
---------------------------------------------------------------------------*/
Foldr = function(func, val, xs)
for i = #xs, 1, -1 do
val = func(xs[i], val)
end
return val
end
Foldl = function(func, val, xs)
for k, v in ipairs(xs) do
val = func(val, v)
end
return val
end
And = function(xs)
for k, v in pairs(xs) do
if v ~= true then return false end
end
return true
end
Or = function(xs)
for k, v in pairs(xs) do
if v == true then return true end
end
return false
end
Any = function(func, xs)
for k, v in pairs(xs) do
if func(v) == true then return true end
end
return false
end
All = function(func, xs)
for k, v in pairs(xs) do
if func(v) ~= true then return false end
end
return true
end
Sum = _G.fp{Foldr, Add, 0}
Product = _G.fp{Foldr, Mul, 1}
Concat = _G.fp{Foldr, Append, {}}
Maximum = _G.fp{Foldl, math.Max, -math.huge}
Minimum = _G.fp{Foldl, math.Min, math.huge}
Snd = _G.fp{select, 2}
Thrd = _G.fp{select, 3}