-
Notifications
You must be signed in to change notification settings - Fork 0
/
list.js
122 lines (115 loc) · 3.51 KB
/
list.js
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
var curry = require('./curry');
var args = require('./args');
var math = require('./math');
var compose = require('./compose');
var utils = require('./utils');
var arity = require('./arity');
var bool = require('./bool');
var id = require('./id');
var reorder = require('./reorder');
var private = {
iterate: function(list, fn, defaultValue) {
var abort = false;
var ret = defaultValue;
for (var i = 0; i < list.length; ++i)
{
fn(list[i], i, list, function(returnValue) {
abort = true;
ret = returnValue;
});
if (abort)
return ret;
}
return ret;
},
find: function(fn, list) {
return private.iterate(list, function(item, index, list, returnWith) {
if (fn(item, index, list))
returnWith({item: item, index: index});
}, {index: -1});
}
};
var listModule = {
take: function(count, list) {
return list.slice(0, Math.min(count, list.length));
},
takeWhile: function(fn, list) {
var index = listModule.find(bool.not(fn), list) - 1;
return index == -1 ? [] : list.slice(0, index);
},
skip: function(count, list) {
return list.slice(count);
},
skipWhile: function(fn, list) {
var index = listModule.find(bool.not(fn), list) - 1;
return index == -1 ? [] : list.slice(index);
},
find: function(fn, list) {
return private.find(fn, list).item;
},
findIndex: function(fn, list) {
return private.find(fn, list).index;
},
findLastIndex: function(fn, list) {
var index = private.find(fn, list.slice().reverse()).index;
return index == -1 ? -1 : list.length - 1 - index;
},
reduce: function(fn, acc, list) {
// deep clone accumulator if passed by reference -- N.B. DOES NOT CLONE FUNCTIONS (USE for with obj in closure instead)
if (utils.isPassedByRef(acc))
acc = JSON.parse(JSON.stringify(acc));
return list.reduce(fn, acc);
},
reduceRight: function(fn, acc, list) {
// deep clone accumulator if passed by reference -- N.B. DOES NOT CLONE FUNCTIONS (USE for with obj in closure instead)
if (utils.isPassedByRef(acc))
acc = JSON.parse(JSON.stringify(acc));
for (var i = list.length - 1; i >= 0 ; --i)
acc = fn(acc, list[i], i, list);
return acc;
},
size: function(list) {
return list.length;
},
head: function(list) {
return list[0];
},
tail: function(list) {
return list.slice(1);
}
};
var curriedList = curry.curryObject(listModule);
// add a selection of curried native Array functions
var _a = curry.curryClassMethods(Array);
utils.extend(curriedList, ['map', 'filter', 'every', 'some', 'indexOf','lastIndexOf', 'sort'].map(function(funcName) {
curriedList[funcName] = _a[funcName];
}));
utils.extend(curriedList, {
concat: reorder.flip(_a.concat),
cloneList: curry.curryOOMethod(Array.prototype.slice, 0),
// add minor variations on natives
contains: compose.compose(math.neq(-1), curriedList.indexOf),
// add aliases
foldl: curriedList.reduce,
foldr: curriedList.reduceRight,
// add inverses
reject: args.applyToArg(bool.not, 1, curriedList.filter),
// add min & max
min: curriedList.reduce(arity.binary(Math.min), Infinity),
max: curriedList.reduce(arity.binary(Math.max), -Infinity)
});
utils.extend(curriedList, {
reverse: compose.compose(_a.reverse, curriedList.cloneList),
findLast: args.applyToArg(compose.compose(_a.reverse, curriedList.cloneList), 2, curriedList.find)
});
utils.extend(curriedList, curry.curryObject({
uniq: function(compare, list) {
compare = compare || math.eqStrict;
return list.reduce(function(acc, item) {
if (!curriedList.contains(item, acc))
acc.push(item);
return acc;
}, []);
}
}));
module.exports = curriedList;