Comparing version 0.0.4 to 0.0.5
223
fx.js
@@ -6,2 +6,4 @@ export const | ||
nop = Symbol('nop'), | ||
not = a => !a, | ||
@@ -21,3 +23,3 @@ | ||
const | ||
export const | ||
hasIter = coll => !!(coll && coll[Symbol.iterator]), | ||
@@ -28,20 +30,60 @@ | ||
collIter = alterIter(valuesIter); | ||
collIter = alterIter(Lvalues); | ||
export function *valuesIter(obj) { | ||
export const go1 = (a, f) => a instanceof Promise ? a.then(f) : f(a); | ||
export const L = {}; | ||
function* Lvalues(obj) { | ||
for (const k in obj) yield obj[k]; | ||
} | ||
L.values = Lvalues; | ||
export function *entriesIter(obj) { | ||
L.entries = function *(obj) { | ||
for (const k in obj) yield [k, obj[k]]; | ||
} | ||
}; | ||
export function *reverseIter(arr) { | ||
L.reverse = function *(arr) { | ||
var l = arr.length; | ||
while (l--) yield arr[l]; | ||
}; | ||
L.tail = function(coll) { | ||
var iter = collIter(coll); | ||
return go1(take(1, iter), _ => iter); | ||
}; | ||
L.headTail = L.head_tail = function(coll) { | ||
var iter = collIter(coll); | ||
return go1(take(1, iter), head => [head, iter]); | ||
}; | ||
L.range = function *(limit) { | ||
var i = -1; | ||
while (++i < limit) yield i; | ||
}; | ||
L.map = curry(function *(f, coll) { | ||
for (const a of coll) yield go1(a, f); | ||
}); | ||
L.filter = curry(function *(f, coll) { | ||
for (const a of collIter(coll)) { | ||
const b = go1(a, f); | ||
if (b instanceof Promise) yield Promise.all([a, b]).then(([a, b]) => b ? a : Promise.reject(nop)); | ||
else if (b) yield a; | ||
} | ||
}); | ||
L.entriesMap = L.eMap = curry(function *(f, coll) { | ||
for (const [k, a] of coll) yield go1(go1(a, f), b => [k, b]); | ||
}); | ||
L.reject = baseReject(L.filter); | ||
function baseReject(filter) { | ||
return curry((f, coll) => filter(pipe(f, not), coll)); | ||
} | ||
export const | ||
then = curry((f, a) => a instanceof Promise ? a.then(f) : f(a)), | ||
call = (f, a) => f(a), | ||
@@ -52,10 +94,2 @@ | ||
export const | ||
push = (a, arr) => (arr.push(a), arr), | ||
push2 = (arr, a) => (arr.push(a), a), | ||
push3 = (arr, a) => (arr.push(a), arr), | ||
flatten = arr => [].concat(...arr), | ||
set = curry(([k, v], obj) => (obj[k] = v, obj)), | ||
@@ -70,13 +104,14 @@ | ||
reduce = curry((f, coll, acc) => { | ||
const iter = collIter(coll); | ||
return then(function (cur) { | ||
return function recur(acc) { | ||
while ((cur = iter.next()) && !cur.done) { | ||
if (cur instanceof Promise) return cur.then(cur => cur.done ? acc : then(recur, f(acc, cur.value))); | ||
const a = cur.value; | ||
acc = acc instanceof Promise ? acc.then(acc => f(acc, a)) : f(acc, a); | ||
} | ||
return acc; | ||
} (acc === undefined ? cur.value : acc); | ||
}, acc === undefined ? iter.next() : acc); | ||
var iter = collIter(coll); | ||
acc = acc === undefined ? iter.next().value : acc; | ||
return function recur() { | ||
let cur; | ||
while (!(cur = iter.next()).done) { | ||
const a = cur.value, acc_ = acc; | ||
acc = go1(a, a => go1(acc_, acc => f(acc, a))); | ||
if (acc instanceof Promise) | ||
return (acc = acc.catch(e => e == nop ? acc_ : Promise.reject(e))).then(recur); | ||
} | ||
return acc; | ||
} (); | ||
}), | ||
@@ -92,68 +127,50 @@ | ||
export const take = curry(function(limit, coll) { | ||
var res = [], iter = collIter(coll); | ||
return function recur() { | ||
let cur; | ||
while (!(cur = iter.next()).done) { | ||
const a = cur.value; | ||
if (a instanceof Promise) return a | ||
.then(a => (res.push(a), res).length == limit ? res : recur()) | ||
.catch(e => e == nop ? recur() : Promise.reject(e)); | ||
res.push(a); | ||
if (res.length == limit) return res; | ||
} | ||
return res; | ||
} (); | ||
}); | ||
export const | ||
lmap = curry((f, coll) => baseLazyLispF(function() { | ||
return then(cur => cur.done ? cur : then(value => ({value}), f(cur.value)), this.iter.next()); | ||
}, coll)), | ||
takeAll = coll => take(Infinity, coll), | ||
map = curry((f, coll) => | ||
hasIter(coll) ? | ||
all(lmap(f, coll)) : | ||
reduce( | ||
(res, [k, a]) => go(f(a), b => (res[k] = b, res)), | ||
entriesIter(coll), | ||
{}) | ||
), | ||
take1 = take(1); | ||
pluck = curry((k, coll) => map(a => a[k], coll)); | ||
export const | ||
head = pipe(take1, ([a]) => a), | ||
tail = coll => takeAll(L.tail(coll)); | ||
export const | ||
lfilter = curry((f, coll) => baseLazyLispF(function() { | ||
var recur = (cur, b) => { | ||
while (!cur.done) { | ||
if (b = f(cur.value)) return then(b => b ? cur : this.next(), b); | ||
if ((cur = this.iter.next()) instanceof Promise) return cur.then(recur); | ||
} | ||
return { done: true } | ||
}; | ||
return then(recur, this.iter.next()); | ||
}, coll)), | ||
map = curry(pipe(L.map, takeAll)), | ||
filter = curry((f, coll) => | ||
hasIter(coll) ? | ||
all(lfilter(f, coll)) : | ||
reduce( | ||
(res, [k, a]) => go(f(a), b => (b && (res[k] = b), res)), | ||
entriesIter(coll), | ||
{}) | ||
), | ||
pluck = curry((k, coll) => map(a => a[k], coll)); | ||
lreject = baseReject(lfilter), | ||
export const | ||
filter = curry(pipe(L.filter, takeAll)), | ||
reject = baseReject(filter); | ||
function baseLazyLispF(next, coll) { | ||
return { | ||
next, | ||
iter: coll[Symbol.iterator](), | ||
[Symbol.iterator]: function() { return this; } | ||
}; | ||
} | ||
function baseReject(filter) { | ||
return curry((f, coll) => filter(pipe(f, not), coll)); | ||
} | ||
export function all(coll) { | ||
return reduce(push3, coll, []); | ||
} | ||
export const | ||
uniqueBy = curry((f, coll) => { | ||
const s = new Set(); | ||
const imobj = !hasIter(coll); | ||
return go( | ||
coll, | ||
imobj ? L.entries : identity, | ||
filter(pipe( | ||
imobj ? last : identity, | ||
f, | ||
b => s.has(b) ? false : s.add(b) | ||
))); | ||
b => s.has(b) ? false : s.add(b))), | ||
imobj ? object : identity); | ||
}), | ||
@@ -176,3 +193,3 @@ | ||
indexBy = curry((f, coll) => | ||
reduce((index, a) => set([f(a), a], index), coll, {})), | ||
reduce((indexed, a) => set([f(a), a], indexed), coll, {})), | ||
@@ -191,8 +208,50 @@ index_by = indexBy; | ||
export function *range(limit) { | ||
var i = -1; | ||
while (++i < limit) yield i; | ||
} | ||
export const | ||
find = curry(pipe(L.filter, head)), | ||
some = curry(pipe(L.filter, take1, _ => _.length == 1)), | ||
every = curry(pipe(L.reject, take1, _ => _.length == 0)); | ||
export const | ||
object = coll => reduce((obj, [k, v]) => (obj[k] = v, obj), coll, {}); | ||
object = coll => reduce((obj, [k, v]) => (obj[k] = v, obj), coll, {}), | ||
entryMap = curry((f, [k, a]) => go1(f(a), b => [k, b])), | ||
eMap = entryMap; | ||
export const C = {}; | ||
C.map = curry(pipe(L.map, _ => [..._], takeAll)); | ||
C.reduce = (f, coll, acc) => reduce(f, [...coll], acc); | ||
C.take = curry((limit, coll) => new Promise(function(resolve) { | ||
var res = []; | ||
var i = -1, j = -1, resolved; | ||
for (const a of coll) { | ||
++i; | ||
Promise.resolve(a).then(a => { | ||
if (resolved) return; | ||
res.push(a); | ||
if (res.length == limit || i == ++j) { | ||
resolved = true; | ||
resolve(res); | ||
} | ||
}).catch(e => e != nop && Promise.reject(e)); | ||
} | ||
})); | ||
C.takeAll = coll => C.take(Infinity, coll); | ||
C.take1 = C.take(1); | ||
C.head = pipe(C.take1, ([a]) => a); | ||
C.tail = coll => C.takeAll(L.tail(coll)); | ||
C.find = curry(pipe(L.filter, C.head)); | ||
C.some = curry(pipe(L.filter, C.take1, _ => _.length == 1)); | ||
C.every = curry(pipe(L.reject, C.take1, _ => _.length == 0)); |
{ | ||
"name": "fxjs2", | ||
"version": "0.0.4", | ||
"version": "0.0.5", | ||
"description": "Functional Extensions for Javascript", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
"test": "mocha -R spec test/**/*.js" | ||
}, | ||
"files": [ | ||
"fx.js", | ||
"index.js", | ||
"LICENSE", | ||
"README.md" | ||
], | ||
"repository": { | ||
@@ -21,3 +27,7 @@ "type": "git", | ||
"esm": "^3.0.80" | ||
}, | ||
"devDependencies": { | ||
"chai": "^4.1.2", | ||
"mocha": "^5.2.0" | ||
} | ||
} |
@@ -9,2 +9,75 @@ ## FxJS - Functional Extensions for Javascript | ||
npm i fxjs2 | ||
``` | ||
``` | ||
### ëĒŠė°¨ | ||
- [map](#map) | ||
- [filter](#filter) | ||
- [reduce](#reduce) | ||
- [take](#take) | ||
- [L.map](#L.map) | ||
- [L.filter](#L.filter) | ||
#### map | ||
```javascript | ||
map(a => a + 10, [1, 2, 3]); | ||
// [11, 12, 13] | ||
``` | ||
#### filter | ||
```javascript | ||
filter(a => a % 2, [1, 2, 3]); | ||
// [1, 3] | ||
``` | ||
#### reduce | ||
```javascript | ||
const add = (a, b) => a + b | ||
reduce(add, [1, 2, 3]); | ||
// 6 | ||
reduce(add, [1, 2, 3], 10); | ||
// 16 | ||
reduce(add, {a: 1, b: 2, c: 3}); | ||
// 6 | ||
await reduce(add, [Promise.resolve(1), 2, 3]) | ||
// 6 | ||
``` | ||
#### take | ||
```javascript | ||
take(1, [1, 2, 3]); | ||
// [1] | ||
take(2, [1, 2, 3]) | ||
// [1, 2] | ||
``` | ||
#### L.map | ||
```javascript | ||
const lazy = L.map(a => a + 10, [1, 2, 3]); | ||
take(2, lazy); | ||
// [11, 12] | ||
``` | ||
#### L.filter | ||
```javascript | ||
const lazy = L.filter(a => a % 2, [1, 2, 3, 4, 5]); | ||
take(2, lazy); | ||
// [1, 3] | ||
``` | ||
```javascript | ||
const lazy = L.filter(a => a % 2, L.map(a => a + 10, [1, 2, 3, 4, 5])); | ||
take(2, lazy); | ||
// [11, 13] | ||
``` | ||
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
Found 1 instance in 1 package
1
83
8409
2
5
178
1