aboutsummaryrefslogtreecommitdiffstats
path: root/lua/mason-core/functional/function.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua/mason-core/functional/function.lua')
-rw-r--r--lua/mason-core/functional/function.lua89
1 files changed, 89 insertions, 0 deletions
diff --git a/lua/mason-core/functional/function.lua b/lua/mason-core/functional/function.lua
new file mode 100644
index 00000000..e85081ce
--- /dev/null
+++ b/lua/mason-core/functional/function.lua
@@ -0,0 +1,89 @@
+local data = require "mason-core.functional.data"
+
+local _ = {}
+
+---@generic T : fun(...)
+---@param fn T
+---@param arity integer
+---@return T
+_.curryN = function(fn, arity)
+ return function(...)
+ local args = data.table_pack(...)
+ if args.n >= arity then
+ return fn(unpack(args, 1, arity))
+ else
+ return _.curryN(_.partial(fn, unpack(args, 1, args.n)), arity - args.n)
+ end
+ end
+end
+
+_.compose = function(...)
+ local functions = data.table_pack(...)
+ assert(functions.n > 0, "compose requires at least one function")
+ return function(...)
+ local result = data.table_pack(...)
+ for i = functions.n, 1, -1 do
+ result = data.table_pack(functions[i](unpack(result, 1, result.n)))
+ end
+ return unpack(result, 1, result.n)
+ end
+end
+
+---@generic T
+---@param fn fun(...): T
+---@return fun(...): T
+_.partial = function(fn, ...)
+ local bound_args = data.table_pack(...)
+ return function(...)
+ local args = data.table_pack(...)
+ local merged_args = {}
+ for i = 1, bound_args.n do
+ merged_args[i] = bound_args[i]
+ end
+ for i = 1, args.n do
+ merged_args[bound_args.n + i] = args[i]
+ end
+ return fn(unpack(merged_args, 1, bound_args.n + args.n))
+ end
+end
+
+_.identity = function(a)
+ return a
+end
+
+_.always = function(a)
+ return function()
+ return a
+ end
+end
+
+_.T = _.always(true)
+_.F = _.always(false)
+
+---@generic T : fun(...)
+---@param fn T
+---@param cache_key_generator (fun(...): string | nil)|nil
+---@return T
+_.memoize = function(fn, cache_key_generator)
+ cache_key_generator = cache_key_generator or _.identity
+ local cache = {}
+ return function(...)
+ local key = cache_key_generator(...)
+ if not cache[key] then
+ cache[key] = data.table_pack(fn(...))
+ end
+ return unpack(cache[key], 1, cache[key].n)
+ end
+end
+
+---@generic T
+---@param fn fun(): T
+---@return fun(): T
+_.lazy = function(fn)
+ local memoized = _.memoize(fn, _.always "lazyval")
+ return function()
+ return memoized()
+ end
+end
+
+return _