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
|
local M = {}
-- shallow copies a table, dst optional.
M.copy = function(src, dst)
dst = dst or {}
for k, v in pairs(src) do
dst[k] = v
end
return dst
end
-- recursively copies a table, dst optional.
-- might implode for infinitely nested tables.
M.deepcopy = function(src, dst)
dst = dst or {}
-- convenience.
if type(src) ~= "table" then return src end
for k, v in pairs(src) do
dst[k] = M.deepcopy(v)
end
return dst
end
-- replaces all values of a table with fn(value).
M.map = function(fn, tbl)
local res = {}
for k, v in pairs(tbl) do
res[k] = fn(v)
end
return res
end
-- in-place version of the above.
M.map_ip = function(fn, tbl)
for k, v in pairs(tbl) do
tbl[k] = fn(v)
end
return tbl -- redundant, technically, but i thought i'd include it anyway.
end
-- discards or keeps values from a table based on a predicate.
-- this one only supports arrays, not maps.
M.filter = function(pred, arr)
local res = {}
for i, v in ipairs(arr) do
if pred(v) then
table.insert(res, v)
end
end
return res
end
M.filter_ip = function(pred, arr) -- in-place.
for i = #arr, 1, -1 do -- we need to iterate backwards here to prevent the.
if not pred(arr[i]) then
table.remove(arr, i)
end
end
return arr
end
-- like filter, but works on map-style tables instead.
M.filter_map = function(pred, map)
local res = {}
for k, v in pairs(map) do
if pred(v) then
res[k] = v
end
end
return res
end
M.filter_map_ip = function(pred, map) -- in-place.
for k, v in pairs(map) do
if not pred(v) then
map[k] = nil
end
end
return map
end
-- "folds" an operation over an array. i.e foldr(*, e, {a, b, c, d}) = a * (b * (c * (d * e))).
M.foldr = function(op, startval, arr)
local res = startval or 0 -- sensible default?
for i = #arr, 1, -1 do
res = op(res, arr[i])
end
return res
end
-- same as above, but the other way i.e ((e * a) * b) * c
M.foldl = function(op, startval, arr)
local res = startval or 0
for i=1, #arr do
res = op(res, arr[i])
end
return res
end
M.sum = function(arr)
return M.foldl(function(a,b) return a+b end, 0, arr)
end
M.product = function(arr)
return M.foldl(function(a,b) return a*b end, 0, arr)
end
return M
|