|
1 -- Prosody IM |
|
2 -- Copyright (C) 2008-2010 Matthew Wild |
|
3 -- Copyright (C) 2008-2010 Waqas Hussain |
|
4 -- |
|
5 -- This project is MIT/X11 licensed. Please see the |
|
6 -- COPYING file in the source package for more information. |
|
7 -- |
|
8 |
|
9 local t_insert, t_sort, t_remove, t_concat |
|
10 = table.insert, table.sort, table.remove, table.concat; |
|
11 |
|
12 local array = {}; |
|
13 local array_base = {}; |
|
14 local array_methods = {}; |
|
15 local array_mt = { __index = array_methods, __tostring = function (array) return array:concat(", "); end }; |
|
16 |
|
17 local function new_array(_, t) |
|
18 return setmetatable(t or {}, array_mt); |
|
19 end |
|
20 |
|
21 function array_mt.__add(a1, a2) |
|
22 local res = new_array(); |
|
23 return res:append(a1):append(a2); |
|
24 end |
|
25 |
|
26 setmetatable(array, { __call = new_array }); |
|
27 |
|
28 function array_base.map(outa, ina, func) |
|
29 for k,v in ipairs(ina) do |
|
30 outa[k] = func(v); |
|
31 end |
|
32 return outa; |
|
33 end |
|
34 |
|
35 function array_base.filter(outa, ina, func) |
|
36 local inplace, start_length = ina == outa, #ina; |
|
37 local write = 1; |
|
38 for read=1,start_length do |
|
39 local v = ina[read]; |
|
40 if func(v) then |
|
41 outa[write] = v; |
|
42 write = write + 1; |
|
43 end |
|
44 end |
|
45 |
|
46 if inplace and write <= start_length then |
|
47 for i=write,start_length do |
|
48 outa[i] = nil; |
|
49 end |
|
50 end |
|
51 |
|
52 return outa; |
|
53 end |
|
54 |
|
55 function array_base.sort(outa, ina, ...) |
|
56 if ina ~= outa then |
|
57 outa:append(ina); |
|
58 end |
|
59 t_sort(outa, ...); |
|
60 return outa; |
|
61 end |
|
62 |
|
63 --- These methods only mutate |
|
64 function array_methods:random() |
|
65 return self[math.random(1,#self)]; |
|
66 end |
|
67 |
|
68 function array_methods:shuffle(outa, ina) |
|
69 local len = #self; |
|
70 for i=1,#self do |
|
71 local r = math.random(i,len); |
|
72 self[i], self[r] = self[r], self[i]; |
|
73 end |
|
74 return self; |
|
75 end |
|
76 |
|
77 function array_methods:reverse() |
|
78 local len = #self-1; |
|
79 for i=len,1,-1 do |
|
80 self:push(self[i]); |
|
81 self:pop(i); |
|
82 end |
|
83 return self; |
|
84 end |
|
85 |
|
86 function array_methods:append(array) |
|
87 local len,len2 = #self, #array; |
|
88 for i=1,len2 do |
|
89 self[len+i] = array[i]; |
|
90 end |
|
91 return self; |
|
92 end |
|
93 |
|
94 array_methods.push = table.insert; |
|
95 array_methods.pop = table.remove; |
|
96 array_methods.concat = table.concat; |
|
97 array_methods.length = function (t) return #t; end |
|
98 |
|
99 --- These methods always create a new array |
|
100 function array.collect(f, s, var) |
|
101 local t, var = {}; |
|
102 while true do |
|
103 var = f(s, var); |
|
104 if var == nil then break; end |
|
105 table.insert(t, var); |
|
106 end |
|
107 return setmetatable(t, array_mt); |
|
108 end |
|
109 |
|
110 --- |
|
111 |
|
112 -- Setup methods from array_base |
|
113 for method, f in pairs(array_base) do |
|
114 local base_method = f; |
|
115 -- Setup global array method which makes new array |
|
116 array[method] = function (old_a, ...) |
|
117 local a = new_array(); |
|
118 return base_method(a, old_a, ...); |
|
119 end |
|
120 -- Setup per-array (mutating) method |
|
121 array_methods[method] = function (self, ...) |
|
122 return base_method(self, self, ...); |
|
123 end |
|
124 end |
|
125 |
|
126 _G.array = array; |
|
127 module("array"); |
|
128 |
|
129 return array; |