-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfnk.js
143 lines (122 loc) · 3.64 KB
/
fnk.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
'use strict';
/*
* Takes two arrays, returns an array with any elements that the arrays do not share.
*/
const arrayDiff = (a, b) => a.filter(x => b.indexOf(x) === -1);
/**
* Returns an iterator function to run fn on x a specified number of times.
* @param function
* @param number of times to iterate over the function
* @return x value to pass into fn, then the function iterates over its own result
*/
const createIterator = (fn, times) => x => {
let result = fn(x);
let i = times - 1;
while (i) {
i--;
result = fn(result);
}
return result;
};
/**
* A memoizer using ES6 maps
* @param function to be memoized
* @return function to take variable args, and utilize the cache.
*/
const cache = func => {
const cache = new Map();
return (...args) => {
const key = [...args]
.map(JSON.stringify)
.join(',');
return cache.has(key) ?
cache.get(key) :
cache.set(key, func(...args))
.get(key);
}
}
/**
* Creates an array of size n filled with value v
* @param number n of items to go into the array
* @param value v of item to fill array with
* @return an array of size n with value v
*/
const fillArray = (n, v) =>
[...Array(parseInt(n, 10))].map(() => v);
/*
* Takes an array or string and a thing and tells you if the thing is in the array or string.
*/
const has = (collection, thing) => collection.indexOf(thing) !== -1;
const hasNot = (collection, thing) => !has(collection, thing);
/**
* Takes an object and returns an array of all of its values.
* @param Obj
* @return Array of values
*/
const values = obj => {
if (obj.values) { return obj.values(); }
let vals = [];
for (const key in obj) {
if (obj.hasOwnProperty(key)){
vals.push(obj[key]);
}
}
return vals;
}
/**
* Does the object have any keys?
*/
const hasKeys = obj => !!Object.keys(obj).length;
/**
* Pads leftly.
*/
const leftPad = (amt, str = '', pad = ' ') => {
while (str.length < amt) {
str += pad;
amt--;
}
return str;
}
/*
* Takes a constructor and a value and tells you if the thing is an instance of the constructor.
*/
const is = (typeclass, thing) => thing ? thing instanceof typeclass : false;
/*
* Shortcut for reducing all the values of an object to a single value.
* Makes parsing objects a bit more functional.
*/
const reduceValues = (obj, callback, starter) => values(obj).reduce(callback, starter);
/**
* Function composition with variable arity (lol jargon)
* @param(s) any number of functions
* @return a function that will take all of the functions, then you can pass a single arg to it.
*/
const compose = (...fns) =>
fns.reduce( (f, g) => (...args) => f( g(...args) ), id);
/**
* Allows you to set min and max range for a number.
* Mostly for preventing semi-random results from getting wacky.
* Usage:
* // Returns a number guaranteed to be between 0 and 100 inclusive but probably tending toward 100.
* const arbitraryWithinBounds = setBounds(0, 100);
* const arbitrarySmallNumber = arbitraryWithinBounds(Math.random() * 1000);
* @param Number minimum bound
* @param Number maximum bound
* @return Function boundsChecker
* @param n Number
* @return Number n, unless n is out of bounds, then it will be the nearest bound.
*/
const setBounds = (min, max) => n =>
Math.max(Math.min(max, stat), min);
// Ensures that a specific value is an array, if the thing is already an array it won't create a nested array.
const toArray = value => [].concat(value);
module.exports = {
fillArray, compose,
has, hasNot,
hasKeys, leftPad,
values, reduceValues,
setBounds, is,
cache, arrayDiff,
createIterator,
toArray
};