This repository has been archived by the owner on Dec 5, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
functional.lua
238 lines (191 loc) · 5.45 KB
/
functional.lua
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
require('pure')
local module = {}
-- Maps 'func' across 'lst', passing each element into 'func' (in order), and constructing a new list from the results.
module.map = function (lst, func)
local result = {}
for i, v in ipairs(lst)
do
result[i] = func(v)
end
return result
end
-- Maps 'func' across 'table', passing every key and value into 'func'.
-- 'func' should return a new key and a new value, which will be used to construct a new table from the results.
-- Because the same key may be returned multiple times, the resultant table may contain fewer elements than the input table.
module.map_pairs = function (table, func)
local result = {}
for k, v in pairs(table)
do
local newKey
local newValue
newKey, newValue = func(k, v)
result[newKey] = newValue
end
return result
end
-- Returns a list of the elements from 'lst' for which 'func' returns a true value.
module.filter = function (lst, func)
local result = {}
for i, v in ipairs(lst)
do
if func(v) then
table.insert(result, v)
end
end
return result
end
-- Returns a table of the key/value pairs from 'table' for which 'func' returns a true value.
module.filter_pairs = function (table, func)
local result = {}
for k, v in pairs(table)
do
if func(v) then
result[k] = v
end
end
return result
end
-- Curries 'func', returning a function that takes the first argument to 'func', and which returns a function taking all the other arguments.
module.curry = function (func)
return function (a)
return function (...)
return func(a, ...)
end
end
end
-- Binds the first arguments of 'func' to the given values. The first argument of 'bindr' is bound to the first argument of 'func', and so on.
module.bindl = function (func, ...)
local args = { ... }
return function (...)
return func(unpack(args), ...)
end
end
-- Binds the last arguments of 'func' to the given values. The last argument of 'bindr' is bound to the last argument to 'func', and so on.
module.bindr = function (func, ...)
local args = { ... }
return function (...)
return func(..., unpack(args))
end
end
-- For the given functor, returns a function which takes one more argument than 'func'.
-- The additional argument will be passed into the function returned by 'func', and the result of that call returned.
module.uncurry = function (func)
return function(...)
local args = { ... }
local f = func(args[1])
return f(unpack(args, 2))
end
end
-- Returns two lists: one composed of the elements from 'lst' that passed predicate 'func', and one composed of elements that failed the predicate.
module.partition = function (lst, func)
local pass = {}
local fail = {}
for i, v in ipairs(lst)
do
if func(v) then
table.insert(pass, v)
else
table.insert(fail, v)
end
end
return pass, fail
end
-- Returns two tables: one composed of the pairs from 'table' that passed predicate 'func', and one composed of pairs that failed the predicate.
module.partition_pairs = function (table, func)
local pass = {}
local fail = {}
for k, v in pairs(table)
do
if func(k, v) then
pass[k] = v
else
fail[k] = v
end
end
return pass, fail
end
-- Creates a table by combining the given lists of keys and values.
-- The key at each index in 'keys' is combined with the value at the same index in 'values'.
-- The two lists must have the same number of elements.
-- It is an error to have two identical keys, as doing so would result in an indeterminate result.
module.zip = function (keys, values)
local table = {}
local count = # keys
if count ~= # values then
error("The lists of keys and values provided to zip() must have the same number of elements", 2)
end
for i = 1, count
do
local key = keys[i]
if table[key] ~= nil then
error("Cannot have two identical keys in the list provided to zip()", 2)
end
table[key] = values[i]
end
return table
end
-- Returns a list of the keys of 'table', and a list of the values of 'table', respectively.
-- The order of the lists is undefined, except that the index of a given key matches the index of its associated value.
module.unzip = function (table)
local keys = {}
local values = {}
for k, v in pairs(table)
do
keys.insert(k)
values.insert(v)
end
return keys, values
end
-- Flattens all recursive lists within 'list' into a one-dimensional list.
module.flatten = function (list)
local result = {}
for i, v in ipairs(list)
do
if type(v) == "table" then
local flattened = module.flatten(v)
for fi, fv in ipairs(flattened)
do
table.insert(result, fv)
end
else
table.insert(result, v)
end
end
return result
end
-- Returns the first element from 'list', or nil if the list is empty.
module.head = function (list)
if not list or # list == 0 then
return nil
else
return list[1]
end
end
-- Returns all but the first element from 'list'. If 'list' only contains one element, returns an empty list. If 'list' is empty, returns nil.
module.tail = function (list)
local head, tail = module.decons(list)
if head == nil then
return nil
else
return tail
end
end
-- Returns the head and the tail of 'list', or nil if the list is empty.
module.decons = function (list)
if not list then
return nil
end
local count = # list
if count == 0 then
return nil
end
local tail = {}
for i = 2, count do
tail[i - 1] = list[i]
end
return list[1], tail
end
-- Sandbox and export the functions in this module under a 'functional' namespace
functional = module.map_pairs(module, function (name, func)
return name, pure.sandbox(func)
end)