1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
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
---@generic T
---@param value T
---@return T
_.identity = function(value)
return value
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(...): any)?
---@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
_.tap = _.curryN(function(fn, value)
fn(value)
return value
end, 2)
return _
|