nodekell
Functional library for nodejs
Import Module
import * as F from "nodekell"
Quick Example
const v = await F.run(
F.range(Infinity),
F.filter(e => e % 2 == 0),
F.map(e => e + 1),
F.take(5),
F.reduce((acc, e) => acc + e));
console.log(v);
const v = await F.run(
F.repeat(2),
F.map(e => e + 1),
F.take(5),
F.distinct,
F.collect);
console.log(v);
Functions / Examples
currying
functional
functional / parallel
functional / string
generator
aggregate
util / else
run
combination left to right functions
first arguments received second functions argument
from second received combine functions
returns promise
const v = await F.run(
F.range(10),
F.filter(e => e % 2 == 0),
F.map(e => e + 1),
F.reduce((acc, e) => acc + e))
console.log(v + 1);
this expands to
const v = await F.reduce((acc, e) => acc + e,
F.map(e => e + 1,
F.filter(e => e % 2 == 0,
F.range(10))));
pipe
combination left to right functions
only first function can use multiple arguments.
return value is promise.
see also compose
const rs = F.pipe(
e => e.sort(),
F.reverse,
F.collect);
const a = [1,5,4,3,2];
const result = await rs(a);
console.log(result);
const double1 = F.pipe(
F.map(e => e + e),
F.collect);
const a = [1,2,3,4];
const r1 = await double1(a);
console.log(r1);
const double2 = F.pipe(
t => t.map(e => e + e));
const a = [1,2,3,4];
const r2 = await double2(a);
console.log(r2);
compose
combination right to left functions
only last function can use multiple arguments.
return value is promise.
see also pipe
const rs = F.compose(
F.collect,
F.reverse,
e => e.sort()
);
const a = [1,5,4,3,2];
const result = await rs(a);
console.log(result);
const double1 = F.compose(
F.collect,
F.map(e => e + e)
);
const a = [1,2,3,4];
const r1 = await double1(a);
console.log(r1);
const double2 = F.compose(
t => t.map(e => e + e));
const a = [1,2,3,4];
const r2 = await double2(a);
console.log(r2);
curry
if all arguments are not given for the function,
it returns the function that stored the argument
const myAdd = F.curry((a,b,c) => a + b + c);
const myAdd1 = myAdd(1);
const myAdd2 = myAdd1(2);
const myAdd3 = myAdd2(3);
console.log(myAdd3);
const myAdd = F.curry((a,b,c) => a + b + c);
const r = myAdd(1,2,3);
console.log(r);
filter
const a = [1,2,3,4,5];
const filtered = F.filter(e=> e % 2 == 0, a)
for await (const e of filtered) {
console.log(e);
}
const r = await F.run(
[1,2,3,4,5],
F.filter(e => e % 2 == 0));
for await (const e of r) {
console.log(e);
}
filterIndexed
filter with loop counter
const a = ["Apple", "Banana", "Orange", "Strawberry"];
const filtered = F.filterIndexed((i, e) => {
return e[i] === "a";
}, a);
for await (const e of filtered) {
console.log(e);
}
filterNot
filter return false
const a = [1,2,3,4,5];
const filtered = F.filterNot(e=> e % 2 == 0, a)
for await (const e of filtered) {
console.log(e);
}
const r = await F.run(
[1,2,3,4,5],
F.filterNot(e => e % 2 == 0));
for await (const e of r) {
console.log(e);
}
map
const a = [1,2,3,4,5];
for await (const e of F.map(e=> e * 2, a)) {
console.log(e);
}
const v = await F.run([1,2,3,4,5],
F.map(e => e + 1),
F.collect);
console.log(v);
mapIndexed
map with loop counter
const a = ['a','b','c','d','e'];
const mapped = F.mapIndexed((i, e) => {
return e + i;
}, a);
for await (const e of mapped) {
console.log(e);
}
take
const a = [1,2,3,4,5];
const t = F.take(3, a);
console.log(await F.collect(t));
const v = await F.run(
F.range(Infinity),
F.take(2),
F.collect
);
console.log(v);
takeWhile
const a = [1,2,3,1,2,3];
const t = F.takeWhile(e => e < 3, a);
console.log(await F.collect(t));
fmap
const a = [[1],[2],[3],[4],[5]];
const f = F.fmap(e => e, a);
console.log(await F.collect(f));
const a = [
[Promise.resolve(1)],
Promise.resolve([2]),
[3],
[4],
[5]];
const f = F.fmap(e => e, a);
console.log(await F.collect(f));
flatMap
same as fmap
flat
const a = [
[Promise.resolve(1)],
Promise.resolve([2]),
[3],
[4],
5];
const f = F.flat(a);
console.log(await F.collect(f));
dflat
Similar to flat, but works recursively
const r = F.dflat([[[1],[2]]],[[3]],[4]);
const c = await F.collect(r);
console.log(c);
const r = F.dflat("HELLO");
const c = await F.collect(r);
console.log(c);
reverse
const a = [1,2,3,4,5];
const t = F.reverse(a);
console.log(await F.collect(t));
forEach
works concurrency
const beginTime = Date.now();
await F.run(
F.range(100),
F.forEach(async e => {
await F.sleep(100)
}));
const endTime = Date.now();
console.log(endTime - beginTime);
forEachIndexed
forEach with loop counter
works concurrency
const beginTime = Date.now();
const arr = ['a','b','c','d','e'];
await F.forEachIndexed(async (i, e) => {
await F.sleep(100);
console.log(i, e);
}, arr);
const endTime = Date.now();
console.log(endTime - beginTime);
zip
const a = [1,2,3,4,5];
const b = [6,7,8,9,10];
const z = F.zip(a, b);
const arr = await F.collect(z);
for (const e of arr) {
console.log(e);
}
zip3
const a = [1,2,3];
const b = [4,5,6];
const c = [7,8,9];
const z = F.zip3(a,b,c);
const arr = await F.collect(z);
for (const e of arr) {
console.log(e);
}
const a = [1,2];
const b = [4,5,6];
const c = [7,8,9];
const z = F.zip3(a,b,c);
const arr = await F.collect(z);
for (const e of arr) {
console.log(e);
}
zipWith
const a = [{id:1}, {id:2}];
const b = [{name:"a"}, {name:"b"}];
const myZip = (f, s) => {
return [f.id, s.name];
};
const z = F.zipWith(myZip,a, b);
const arr = await F.collect(z);
for (const e of arr) {
console.log(e);
}
zipWith3
const a = [1,2,3];
const b = [4,5,6];
const c = [7,8,9];
const z = F.zipWith3((f,s,t)=>f+s+t, a, b,c);
const arr = await F.collect(z);
console.log(arr);
drop
drop first element
const a = [1,2,3,4,5];
const r = F.drop(3, a)
const result = await F.collect(r);
console.log(result);
const a = [1,2,3,4,5];
const r = F.drop(Infinity, a)
const result = await F.collect(r);
console.log(result);
dropLast
drop last element
const a = [1,2,3,4,5];
const r = F.dropLast(3, a)
const result = await F.collect(r);
console.log(result);
const a = [1,2,3,4,5];
const r = F.dropLast(Infinity, a)
const result = await F.collect(r);
console.log(result);
dropWhile
const a = [1,2,3,4,1];
const r = F.dropWhile(e=> e < 3, a)
const result = await F.collect(r);
console.log(result);
const a = [Promise.resolve(1),2,3,4,1];
const r = F.dropWhile(e=> e < 3, a)
const result = await F.collect(r);
console.log(result);
emptyThen
const v = await F.run(F.range(Infinity),
F.take(0),
F.emptyThen([1,2,3,4,5]),
F.map(e => e + 1),
F.collect);
console.log(v);
const v = await F.run(F.range(Infinity),
F.take(0),
F.emptyThen(()=> { return [1,2,3] }),
F.map(e => e + 1),
F.collect)
console.log(v);
const v = await F.run(F.range(Infinity),
F.take(3),
F.emptyThen(([9,9,9]),
F.map(e => e + 1),
F.collect);
console.log(v);
distinct
const a = [1,2,1,2,2,3];
const r = F.distinct(a);
const result = await F.collect(r);
console.log(result);
distinctBy
const a = [{num:1}, {num:1}, {num:2}];
const r = F.distinctBy(e=>e.num, a);
const result = await F.collect(r);
for (const m of result) {
console.log(m);
}
distinctUntilChanged
const a = [{num:1}, {num:1}, {num:2}];
const r = F.distinctUntilChanged(a);
for await (const e of r) {
console.log(e);
}
const a = [1,2,2,3,3,3,4,4,5,5,5,5];
const r = F.distinctUntilChanged(a);
for await (const e of r) {
console.log(e);
}
distinctUntilChangedBy
const a = [{num:1}, {num:1}, {num:2}];
const r = F.distinctUntilChangedBy(e => e.num, a);
for await (const e of r) {
console.log(e);
}
const a = [1,2,2,3,3,3,4,4,5,5,5,5];
const r = F.distinctUntilChangedBy(F.identity, a);
for await (const e of r) {
console.log(e);
}
splitBy
to iterable from any
const helloWorld = "hello world";
const r = await F.splitBy(e=>e.split(" "), helloWorld);
for await(const e of r) {
console.log(e);
}
innerJoin
deprecated
This function will be replaced by another feature
same as leftInnerJoin
leftInnerJoin
deprecated
support Map, Object({})
const a = [{id:1, name:"foo"}, {id: 2, name:"bar"}, {id: 3, name:"hoo"}];
const b = [{id:1, value:3}, {id: 2, value: 4}];
const j = await F.innerJoin((v1,v2) => v1.id === v2.id , a, b);
const r = await F.collect(j);
console.log(r);
rightInnerJoin
deprecated
support Map, object({})
the result is the same as innerJoin, but the output order is right iterator
const a = [{id:1, value:3}];
const b = [{id:1, name:"foo"}, {id: 2, name:"bar"}, {id: 3, name:"hoo"}];
const j = await F.rightInnerJoin((v1,v2) => v1.id === v2.id , a, b);
const r = await F.collect(j);
console.log(r);
outerJoin
deprecated
same as leftOuterJoin
leftOuterJoin
deprecated
support Map, object({})
const a = [{id:1, name:"foo"}, {id: 2, name:"bar"}, {id: 3, name:"hoo"}];
const b = [{id:1, value:3}, {id: 2, value: 4}];
const j = await F.outerJoin((v1,v2) => v1.id === v2.id, a, b);
const r = await F.collect(j)
console.log(r);
rightOuterJoin
deprecated
support Map, object({})
const a = [{id:1, value:3}];
const b = [{id:1, name:"foo"}, {id: 1, name:"bar"}, {id: 1, name:"hoo"}];
const j = await F.rightOuterJoin((v1,v2) => v1.id === v2.id , a, b);
const r = await F.collect(j);
console.log(r);
then
like promise then
see also tap
const v = await F.run([1,2,3,4,5],
F.then(async function*(iter) {
for await(const e of iter) {
console.log(e);
yield e;
}
}),
F.map(e => e + 1),
F.collect);
console.log(v);
const v = await F.run([1,2,3,4,5],
F.then(iter => {
return iter;
}),
F.collect);
console.log(v);
tap
call first argument with second argument
then returns the second argument
return promise wrap
see also then
see also peek
const v = await F.run([1,2,3,4,5],
F.tap(console.log),
F.map(e => e + 1),
F.collect);
concat
combines two iterables
const c = F.concat([1,2,3],[4,5,6]);
for await(const e of c) {
console.log(e);
}
const v = await F.run(
F.concat([1,2,3],[4,5,6]),
F.collect);
console.log(v);
union
same as concat
scanl
const s = F.scanl((a,b) => a + b, 0, [1,2,3]);
const r = await F.collect(s);
console.log(r);
const r = F.scanl((a, b) => a/b, 64, [4,2,1]);
const r = await F.collect(s);
console.log(r);
scanl1
const s = F.scanl((a,b) => a + b, [1,2,3]);
const r = await F.collect(s);
console.log(r);
const r = F.scanl1((a, b) => a/b, [64,4,2,1]);
const r = await F.collect(s);
console.log(r);
buffer
creates a list by dividing the iterator at specified interval
const b = F.buffer(1, [1,2,3,4,5]);
const c = await F.collect(b);
console.log(c);
const b = F.buffer(2, [1,2,3,4,5]);
const c = await F.collect(b);
console.log(c);
peek
function that perform a function on each element like a map but returns the original instead of the result
this function is useful for debugging.
see also tap
const v = await F.run([1,2,3,4,5],
F.map(e => e + 1),
F.peek(console.log),
F.map(e => e + 1),
F.collect);
const a = [1,2,3,4,5];
const p = F.peek(e=> e + 1, a)
const result = await F.collect(p);
console.log(result);
keys
Gets only the Key value from the Collection object.
When an Iterable object traverses into an Array, returns an asynciterator thataverses only the first element.
const m = new Map([["a", 1], ["b", 2]]);
for await(const k of F.keys(m)) {
console.log(k);
}
const a = async function *() {
yield [1, 2];
yield [3, 4];
yield [5, 6];
};
for await (const e of F.keys(a())) {
console.log(e);
}
values
Gets only the Value from the Collection object.
When an Iterable object traverses into an Array, returns an asynciterator that averses only the second element.
const m = new Map([["a", 1], ["b", 2]]);
for await(const k of F.values(m)) {
console.log(k);
}
const a = async function *() {
yield [1, 2];
yield [3, 4];
yield [5, 6];
};
for await (const e of F.values(a())) {
console.log(e);
}
removeFirst
Iterates through A and removes the first element that satisfies the condition.
const arr = [1, 2, 3, 4];
for await (const e of F.removeFirst(1, arr)) {
console.log(e);
}
const arr = [1, 2, 3, 4];
const r = F.removeFirst((e) => e % 2 === 0, arr);
for await (const e of r) {
console.log(e);
}
updateAt
Update itererator to the index position
const arr = [1,2,3,4,5];
const u = F.updateAt(
99,
0,
arr
);
for await (const e of u) {
console.log(e);
}
updateFirst
In itererator, update the first value that matches 2nd argument to 3rd argument.
const arr = [1, 2, 3];
const r = F.updateFirst(
99,
1,
arr);
for await (const e of r) {
console.log(e);
}
parallel_set_fetch_count
Set the fetch count of the parallel functions.
after setting, the parallel function is called by count at the same time.
default fetch count is 100
F.parallel_set_fetch_count(3);
await F.run(
F.range(Infinity),
F.pmap(async e =>{
console.log(e);
return e + 1;
}),
F.take(1),
F.collect);
F.parallel_set_fetch_count(200);
await F.run(
F.range(Infinity),
F.pmap(async e =>{
console.log(e);
return e + 1;
}),
F.take(1),
F.collect);
pfilter
Same as filter, but calls a fetch count of functions concurrently.
useful for async function or return promise.
const v = await F.run(
F.range(Infinity),
F.pfilter(async e =>{
console.log(e);
return e % 2 === 0;
}),
F.take(2),
F.collect);
console.log(v);
pmap
Same as map, but calls a fetch count of functions concurrently.
useful for async function or return promise.
const v = await F.run(
F.range(Infinity),
F.pmap(async e =>{
console.log(e);
return e + 1;
}),
F.take(2),
F.collect);
console.log(v);
pfmap
Same as fmap, but calls a fetch count of functions concurrently.
useful for async function or return promise.
const v = await F.run(
F.range(Infinity),
F.map(e=> [e]),
F.pfmap(async e =>{
console.log(e);
e.push(42);
return e ;
}),
F.take(5),
F.collect);
console.log(v);
pcalls
- async function generator
const gfn2 = async function* () {
yield _ => Promise.resolve(1);
yield _ => 2;
yield async _ => await Promise.resolve(3);
yield async _ => await 4;
};
const c = F.pcalls(gfn2());
const r = await F.collect(c);
console.log(r);
- call vaarg async functions
Promise.all([fn1(),fn2(),fn3(),fn4()])
const fn1 = () => {
return 1;
};
const fn2 = () => {
return Promise.resolve(2);
};
const fn3 = async () => {
return 3;
};
const fn4 = async () => {
return Promise.resolve(4);
};
const c = F.pcalls(fn1, fn2, fn3, fn4);
const r = await F.collect(c);
console.log(r);
reFind
Use regular expression
return first matching in str
const r = F.reFind(/H(\d)/, "H1ello H2World");
console.log(r);
reFindSubmatch
Use regular expression
return first matching in str and groups
const r = F.reFindSubmatch(/H(\d)/, "H1ello H2World");
console.log(r[0]);
console.log(r[1]);
reFindAll
Use regular expression
return all matching in str
const r = F.reFindAll(/H(\d)/, "H1ello H2World");
console.log(r);
reFindAllSubmatch
Use regular expression
return all matching in str and groups
const r = F.reFindAllSubmatch(/H(\d)/, "H1ello H2World");
console.log(r[0][0]);
console.log(r[0][1]);
console.log(r[1][0]);
console.log(r[1][1]);
range
for (const e of F.range(10)) {
console.log(e);
}
for (const e of F.range(10, 0, -1)) {
console.log(e);
}
seq
make iterable(array, set, map, iteratorObject) to asyncIterator
const a = [1,2,3,4,5];
for await(const e of F.seq(a)) {
console.log(e);
}
const a = new Map([[1,2],[3,4]]);
for await(const e of F.seq(a)) {
console.log(e);
}
repeat
const r = F.repeat(3);
for await(const e of r) {
console.log(e);
}
const v = await F.run(
F.repeat(1),
F.map(e => e + 1),
F.take(5),
F.collect);
console.log(v);
const r = F.repeat(()=>{return 3;});
for await(const e of r) {
console.log(e);
}
const r = F.repeat(3, 5);
for await(const e of r) {
console.log(e);
}
rangeInterval
first argument is set to the repeat interval
for await (const e of F.rangeInterval(100, 5)) {
console.log(e);
}
for await (const e of F.rangeInterval(100, 5, 0, -1)) {
console.log(e);
}
iterate
apply a function to an argument to produce a sequence
const r = await F.run(
F.iterate(F.inc, 1),
F.take(5),
F.collect);
console.log(r);
const fibo = (a) => [a[1], a[0] + a[1]];
const r = await F.run(
F.iterate(fibo, [0, 1]),
F.map(F.head),
F.take(10),
F.collect);
console.log(r);
enumerate
like python enumerate
const arr = ["a", "b", "c", "d", "e"];
for await (const [i, e] of F.enumerate(arr)) {
console.log(i, e);
}
foldl
const a = [1,2,3,4,5];
const sum = await F.foldl((acc, e) => acc + e, 0, a);
console.log(sum);
const a = ["w","o","r","l","d"];
const sum = await F.foldl((acc, e) => acc + e, "hello", a);
console.log(sum);
foldl1
take 1 items and call foldl
const a = [1,2,3,4,5];
const sum = await F.foldl1((acc, e) => acc + e, a);
console.log(sum);
reduce
same as foldl1
const a = [1,2,3,4,5];
const sum = await F.reduce((acc, e) => acc + e, a);
console.log(sum);
juxtA
const a = await F.juxtA([Math.max, Math.min], [1,2,3,4,5]);
console.log(a);
const a = await F.juxtA([Math.max, Math.min], []);
console.log(a);
foldr
const arr = [1,2,3,4,5];
const r = await F.foldr((a, b) => a + b, 0, arr);
console.log(r);
const arr = [64,2,1];
const r = await F.foldr((a, b) => a / b, 1, arr);
console.log(r);
const arr = ["1","2","3","4"];
const r = await F.foldr((a, b) => a + b, "5", arr);
console.log(r);
foldr1
const arr = [1,2,3,4,5];
const r = await F.foldr1((a, b) => a + b, 0, arr);
console.log(r);
const arr = [64,2,1];
const r = await F.foldr1((a, b) => a / b, arr);
console.log(r);
const arr = ["1","2","3","4","5"];
const r = await F.foldr1((a, b) => a + b, arr);
console.log(r);
collect
iterator or asyncIterator to Array
const mapped = F.map(e => e + 1, a);
console.log(mapped);
const collected = await F.collect(mapped);
console.log(collected);
const v = await F.run(
F.range(Infinity),
F.filter(e => (e % 3) === 0),
F.map(e => e + 1),
F.take(5),
F.collect);
console.log(v);
collectMap
const a = [[1,2],[3,4]];
const m = await F.collectMap(a);
for(const [k,v] of m) {
console.log(k, v);
}
collectSet
const a = [1,2,3,1,2,3];
const m = await F.collectSet(a);
for(const e of m) {
console.log(e);
}
const a = "hello world";
const m = await F.collectSet(a);
for(const e of m) {
console.log(e);
}
collectObject
const a = [[1,2],[3,4]];
const m = await F.collectObject(a);
console.log(m);
collectInt8
collect native array(char)
support async generator(collect + Int8Array.from)
if the element is not a number, 0 is assigned
see also collect
const arr = [1,2,3,4];
const c = await F.collectInt8(arr);
console.log(c);
collectInt16
collect native array(short)
support async generator(collect + Int16Array.from)
if the element is not a number, 0 is assigned
see also collect
const arr = [1,2,3,4];
const c = await F.collectInt16(arr);
console.log(c);
collectInt32
collect native array(int32)
support async generator(collect + Int32Array.from)
if the element is not a number, 0 is assigned
see also collect
const arr = [1,2,3,4];
const c = await F.collectInt32(arr);
console.log(c);
collectUint8
collect native array(unsigned char)
support async generator(collect + Uint8Array.from)
if the element is not a number, 0 is assigned
see also collect
const arr = [1,2,3,4];
const c = await F.collectUint8(arr);
console.log(c);
collectUint16
collect native array(unsigned short)
support async generator(collect + Uint16Array.from)
if the element is not a number, 0 is assigned
see also collect
const arr = [1,2,3,4];
const c = await F.collectUint16(arr);
console.log(c);
collectUint32
collect native array(unsigned int32)
support async generator(collect + Uint32Array.from)
if the element is not a number, 0 is assigned
see also collect
const arr = [1,2,3,4];
const c = await F.collectUint32(arr);
console.log(c);
collectUint8Clamped
collect native array(unsigned char)
support async generator(collect + Uint8ClampedArray.from)
if the element is not a number, 0 is assigned
see also collect
const arr = [1,2,3,4];
const c = await F.collectUint8Clamped(arr);
console.log(c);
maxBy
const a = [10,9,8,7];
const r = await F.maxBy(e => e, a);
console.log(r);
const a = [1,10,9,8,7,11];
const r = await F.maxBy(e => Math.floor(e/10), a)
console.log(r);
minBy
const a = [0,10,9,8,7];
const r = await F.minBy(e => e, a);
console.log(r);
const a = [7,10,9,8,1,11];
const r = await F.minBy(e => Math.floor(e/10), a)
console.log(r);
max
const a = [Promise.resolve(10),9,8,7];
const r = await F.max(a);
console.log(r);
min
const a = [10,9,8,Promise.resolve(7)];
const r = await F.min(a);
console.log(r);
some
const a = [1,2,3,4,5];
const r = await F.some(e=> e % 2 == 0, a);
console.log(r);
const r = await F.run(
F.range(Infinity),
F.some(e=> Promise.resolve(e > 100))
);
console.log(r);
every
const a = [1,2,3,4,5];
const r = await F.every(e=> e >= 0, a);
console.log(r);
const a = [1,2,3,4,5];
const r = await F.every(e=> Promise.resolve(e < 3), a);
console.log(r);
count
const a = [1,2,3,4,5];
const n = await F.count(a);
console.log(n);
sum
const a = [1,2,3,4,5];
const n = await F.sum(a);
console.log(n);
const a = "abcde";
const n = await F.sum(a);
console.log(n);
average
const a = [1,2,3,4,5];
const s = await F.average(a);
console.log(s);
const a = [1.0,2.0,3.0,4.0,5.5];
const s = await F.average(a)
console.log(s);
groupBy
returns a Map that is aggregated through a function.
key is the return value of the function, and value is the source.
const a = [
{type: "tea",
price: 1},
{type: "tea",
price: 2},
{type: "phone",
price: 3},
{type: "phone",
price: 4},
];
const r = await F.groupBy(e => e.type, a);
console.log(r.get("tea"));
console.log(r.get("phone"));
orderBy
const a = [{ year: 1990 }, { year: 2005 }, { year: 1958 }];
const ASC = 'ASC';
const DESC = 'desc';
const sortedByASC0 = F.sortBy(e => e.year, F.asc, a);
const sortedByASC1 = F.sortBy(e => e.year, ASC, a);
const sortedByDESC0 = F.sortBy(e => e.year, F.desc, a);
const sortedByDESC1 = F.sortBy(e => e.year, DESC, a);
await F.collect(sortedByASC0);
await F.collect(sortedByDESC1);
const a = [3, 6, 2, 3, 7, 10, 23, 21, 22, 16, 13, 14, 17, 20];
const sortedByASC = F.sortBy(e => e, F.asc, a);
const sortedByDESC = F.sortBy(e => e, F.desc, a);
await F.collect(sortedByASC);
await F.collect(sortedbyDESC);
const a = 'Haskell Brooks Curry';
const sortedByASC = F.sortBy(e => e, F.asc, a);
const sortedByDESC = F.sortBy(e => e, F.desc, a);
await F.collect(sortedByASC).then(e => [e.join('')]);
await F.collect(sortedByDESC).then(e => [e.join('')]);
order
const a = [3, 6, 2, 3, 7, 10, 23, 21, 22, 16, 13, 14, 17, 20];
const sortedByASC = F.sort(F.asc, a);
const sortedByDESC = F.sort(F.desc, a);
await F.collect(sortedByASC);
await F.collect(sortedbyDESC);
const a = 'Haskell Brooks Curry';
const sortedByASC = F.sort(F.asc, a);
const sortedByDESC = F.sort(F.desc, a);
await F.collect(sortedByASC).then(e => [e.join('')]);
await F.collect(sortedByDESC).then(e => [e.join('')]);
sortBy
sorts an array
Returns a new sorted array.
const arr = [4, 3, 2, 5, 1];
const res = await F.sortBy((a, b) => a - b, arr);
console.log(res);
sort
sorts an array
Returns a new sorted array.
const arr = [4, 3, 2, 5, 1];
const res = await F.sortBy(arr);
console.log(res);
frequencies
returns a Map. keys are the items that remove duplicates
value is the number of times key appears
const arr = [1,1,2,3,4,5,5];
const r = await F.frequencies(arr);
console.log(r);
frequenciesBy
returns a Map. keys are the items that remove duplicates
value is the number of times key appears
const arr = [1,1,2,3,4,5,5];
const r = await F.frequenciesBy(F.identity, arr);
console.log(r);
const obj = [{a:1},{a:2},{a:1},{a:3}];
const r = await F.frequenciesBy(e => e.a, obj);
console.log(r);
associateBy
returns a Map using iterator.
when the function returns Array
it uses the first argument as key and the second argument as value.
when not in an array, the key and value are both return values.
const arr0 = [1, 2, 3];
const m0 = await F.associateBy(e => [e, e * 2], arr0);
console.log(m0);
const arr1 = [1, 2, 3];
const m1 = await F.associateBy(e => e + 1, arr1);
console.log(m1);
block
- await promise
- Fetch all the elements of type iterator.
When an element returns a promise, it waits for it to finish.
- Fetch all elements of async iterator type.
const r = await F.run([1,2,3,4,5],
F.map(SomethingNetworkJob),
F.map(console.log),
F.block);
const somethingNetworkJob = Promise.resolve(1);
const somthingNetworkIterator = async function*() {
yield 1;
};
await F.block(somethingNetworkJob, somthingNetworkIterator());
_
always returns true when used in equals
always matches when used in match
const r = F.equals(1, F._);
console.log(r);
const value = [1, 2];
F.match(value,
[0, 1], () => console.log("match [0, 1]"),
F._, () => console.log("match F._")
);
juxtO
Similar get
, get the value of an array element from an object or map.
const r0 = await juxtO(["A","C"], {A:1,B:2,C:3});
console.log(r0);
const r1 = await juxtO(["A","C"], {});
console.log(r1);
const r2 = await juxtO(["A","C"], new Map([["A", 1], ["B", 2], ["C", 3]]));
console.log(r2);
sleep
like other language
const beginDate = Date.now();
await F.sleep(1000);
const endDate = Date.now();
console.log(endDate - beginDate);
head
get first element
warning: if use head for generator, result is not the same
const a = [1,2,3,4,5];
console.log(await F.head(a));
console.log(await F.head(a));
const a = F.seq([10,9,8,7]);
console.log(await F.head(a));
console.log(await F.head(a));
console.log(await F.head(a));
const a = [];
try{
await F.head(a);
}catch(e) {
console.log(e);
}
tail
get from the second
warning: if use tail for generator, result is not the same
const a = [1,2,3,4,5];
const t = F.tail(a);
console.log(await F.collect(t));
const a = F.seq([10,9,8,7]);
for await (const e of F.tail(a)){
console.log(e);
}
for await (const e of a) {
console.log("a is empty");
}
interval
works like built-in function setInterval
- timer works same time start of the function
- available async function.
- only one function is executed at a time.
F.interval(10, async () => {
await F.sleep(1000);
console.log("WORK!");
});
timeout
@changed iterator timeout use withTimeout instead.
const foo = async () => {
await F.sleep(1);
return 1;
};
const v = await F.timeout(40, foo());
console.log(v);
try{
await F.timeout(40, async ()=>{
await F.sleep(1000);
});
} catch(e) {
console.log(e);
}
withTimeout
it is effective to use timeout at the bottom of the run
const res = [];
try{
const iter = await F.run(
F.range(Infinity),
F.map(e => e + 1),
F.map(async e => {
await F.sleep(5);
return e;
}),
F.take(10)
F.withTimeout(40));
for await (const e of iter) {
res.push(e);
}
} catch(ex) {
console.log(ex);
}
console.log(res);
try{
const a = [1,2,3,4,5];
const t = F.withTimeout(50,
F.map(async e => {
await F.sleep(5);
return e;
}, a));
const v = await F.collect(t);
console.log(v);
}catch(ex) {
console.log(ex);
}
isNil
return false null, undefined, NaN true otherwise
console.log(F.isNil(NaN));
console.log(F.isNil(undefined));
console.log(F.isNil(null));
console.log(F.isNil("null"));
console.log(F.isNil("NaN"));
console.log(F.isNil(0));
console.log(F.isNil(false));
console.log(F.isNil([]));
console.log(F.isNil({}));
cond
Requires an even number of arguments
if the first argument is true, it returns the second argument
const r = await F.cond(
false, "ff",
true, "tt",
F.otherwise, "oo"
);
console.log(r);
const r = await F.cond(
Promise.resolve(false), "ff",
Promise.resolve(true), "tt",
F.otherwise, "oo"
);
console.log(r);
otherwise
if (F.otherwise) {
console.log("WORK!");
}
if (F.otherwise()) {
console.log("WORK!");
}
get
call get function or object property
if there is no value, returns undefined
see also prop
see also getOrElse
const obj = { name: "hello", value: 42 };
console.log(F.get("name", obj));
const m = new Map([
["name", "hello map"]
]);
console.log(F.get("name", m));
console.log(F.get("size", m));
getOrElse
if object have a get function,
call it or get the properties of that object.
if there is no value, it returns defaultValue.
support Map, Set, any Object
see also get
const m = new Map([
["name", "hello map"],
["value", 84]
]);
const r0 = F.getOrElse("name", "world", m);
console.log(r0);
const r1 = F.getOrElse("foo", "world", m);
console.log(r1);
prop
get object property
if there is no value, returns undefined
see also get
const obj = { name: "hello", value: 42 };
console.log(F.prop("name", obj));
propOrElse
get the properties of that object.
if there is no value, it returns defaultValue.
see also prop
const arr = [1, 2, 3];
const r0 = F.propOrElse("0", 100, arr);
console.log(r0);
const r1 = F.propOrElse("5", 100, arr);
console.log(r1);
has
if there is a has function, check if the value is true after the call. if the has function is missing or returned false, check that the property is not undefined.
const r = F.has("hello", {hello:"world"});
console.log(r);
const r = F.has("hello", new Map([["hello","world"]]));
console.log(r);
const r = F.has("size", new Map());
console.log(r);
find
const arr = [{a:"a1"}, {b:"a2"}, {a:"a3"}];
const r = await F.find(e => "a" in e , arr);
console.log(r);
const arr = [{a:"a1"}, {b:"a2"}, {a:"a3"}];
const r = await F.find(e => "hello" in e , arr);
console.log(r);
find
returns first element
const arr = [{a:"a1"}, {b:"a2"}, {a:"a3"}];
const r = await F.find(e => "a" in e , arr);
console.log(r);
const arr = [{a:"a1"}, {b:"a2"}, {a:"a3"}];
const r = await F.find(e => "hello" in e , arr);
console.log(r);
findLast
returns last element
const arr = [{a:"a1"}, {b:"a2"}, {a:"a3"}];
const r = await F.findLast(e => "a" in e , arr);
console.log(r);
const arr = [{a:"a1"}, {b:"a2"}, {a:"a3"}];
const r = await F.findLast(e => "hello" in e , arr);
console.log(r);
memoize
result of the call is stored in the internal cache, and the next call returns the result of the cache
function returns promise
const memFn = () => {
console.log("callOnce");
};
const m = F.memoize(memFn);
await m();
await m();
await m();
const beginTime = Date.now();
const memFibo = F.memoize(async (n) => {
if (n === 0) return 0;
if (n === 1) return 1;
return await memFibo(n - 1) + await memFibo(n - 2);
});
console.log(await memFibo(30));
console.log(`Elapsed time:${Date.now()-beginTime}msec`);
memoizeBy
result of the call is stored in the internal cache, and the next call returns the result of the cache
first argument is the key value to be stored in the internal cache
function returns promise
const memFn = () => {
console.log("callOnce");
};
const m = F.memoizeBy(F.identity, memFn);
await m();
await m();
await m();
const beginTime = Date.now();
const memFibo = F.memoizeBy(F.identity, async (n) => {
if (n === 0) return 0;
if (n === 1) return 1;
return await memFibo(n - 1) + await memFibo(n - 2);
});
console.log(await memFibo(30));
console.log(`Elapsed time:${Date.now()-beginTime}msec`);
random
internally use crypto.randomBytes
const r0 = F.random();
const r1 = F.random(10);
const r2 = F.random(1, 42);
equals
compares deep strict equals
const a = 1;
F.equals(a, 1);
F.equals(a, 0);
const o = {a:1};
F.equals({a:1}, o);
F.equals(NaN, NaN);
F.equals([0,1], [0,1]);
shuffle
return a random permutation of iterator
await is not required to use for an array.
const arr = [1,2,3,4,5];
const sf = F.shuffle(arr);
console.log(sf);
const a = function*() {
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
};
const sf = await F.shuffle(a());
console.log(sf);
const a = async function*() {
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
};
const sf = await F.shuffle(a());
console.log(sf);
sample
return a random element of iterator
await is not required to use for an array.
const r = F.sample([1,2,3,4,5,6]);
console.log(r);
const r = await F.sample(F.range(100));
console.log(r);
match
pattern matching
call or return first match
From the second argument requires a pair of arguments.
pair first argument is the value to compare, second argument is the function to use
F._ matches all patterns.
see also _
const value = [1, 2];
F.match(value,
[0, 1], () => console.log("match [0, 1]"),
[1, F._], () => console.log("match [1, any]")
);
const value = [1, 2];
const res = F.match(value,
[0, 1], () => 3,
[1, 2], () => 4
);
console.log("match returns " + res);
fnil
first argument is the calling function. from the second argument,
the argument is entered as the first argument.
returns a function calls first argument,
if a function has a argument, it acts as a substitute for an existing argument.
function sayHello(who) {
console.log("hello " + who);
}
const sayHelloWithDefault = F.fnil(sayHello, "javascript");
sayHelloWithDefault();
sayHelloWithDefault("leanne");
assign
curry with Object.assign
Returns the target object.
const obj0 = { a: 1 };
const obj1 = { b: 1 };
const r = F.assign(obj0);
console.log(r(obj1));
assign3
curry with Object.assign
Returns the target object.
must have at least 3 arguments
const obj0 = { a: 1 };
const obj1 = { b: 1 };
const obj2 = { c: 1 };
const r = F.assign3(obj0, obj1);
console.log(r(obj2));
mergeMap
Create a new Map by combining the arguments of the function.
If the key exists, the value on the right is used.
const m1 = new Map([[1, 2], [3, 4]]);
const m2 = new Map([[5, 6], [7, 8]]);
const r1 = await F.mergeMap(m1, m2);
console.log(r1);
const m3 = new Map([[1, 2], [3, 4]]);
const o1 = { 5: 6, 7: 8 };
const r2 = await F.mergeMap(m3, o1);
console.log(r2);
mergeMapRight
Create a new Map by combining the arguments of the function.
If the key exists, the value on the left is used.
const m1 = new Map([[1, 2], [3, 4]]);
const m2 = new Map([[5, 6], [7, 8]]);
const r1 = await F.mergeMapRight(m1, m2);
console.log(r1);
const m2 = new Map([[1, 2], [3, 4]]);
const o2 = { 5: 6, 7: 8 };
const r2 = await F.mergeMapRight(m2, o2);
console.log(r2);
mergeObject
Create a new object by combining the arguments of the function.
If the key exists, the value on the right is used.
const m1 = new Map([[1, 2], [3, 4]]);
const o1 = { 5: 6, 7: 8 };
const r1 = await F.mergeObject(m1, o1);
console.log(r1);
mergeObjectRight
Create a new object by combining the arguments of the function.
If the key exists, the value on the left is used.
const m1 = new Map([[1, 2], [3, 4]]);
const o1 = { 5: 6, 7: 8 };
const r1 = await F.mergeObjectRight(m1, o1);
console.log(r1);
comparator
Creates a function that can be used as a comparison using '<' on an existing '-'.
const cmp = F.comparator((a, b) => a < b);
console.log(cmp(1, 2));
const arr = [5, 4, 1, 2, 3];
arr.sort(F.comparator((a, b) => a < b));
console.log(arr);
const arr = [5, 4, 1, 2, 3];
const r0 = await F.sortBy(F.comparator((a, b) => a > b), arr);
console.log(r0);
insertAt
Add iterator to the index position of iterator received as an argument.
If index is greater than the length of iterator, it is added to the end of iterator.
const arr = [1,2,3,4,5];
const ins = F.insertAt(6, 0, arr);
const r = await F.collect(ins);
console.log(r);
const arr = [1,2,3,4,5];
const ins = F.insertAt(6, Infinity, arr);
const r = await F.collect(ins);
console.log(r);
doto
It takes a value and a function and calls the function by value.
Pass the value to the first argument when calling the function.
const r = await F.doto({a: 1}, (v) => {
v.a = 3;
});
console.log(r);
const r = await F.doto({a: 1}, (v) => {
v.a = 3;
}, (v) => {
v.b = 2;
});
console.log(r);
isPrimitive
check string, number, bigint, boolean, null, undefined, and symbol.
notice
bigint is also a primitive type,
but due to typescript compatibility issues the correct type may not be displayed.
F.isPrimitive(1)
F.isPrimitive(null)
F.isPrimitive(0)
F.isPrimitive(Symbol("HELLO"));
F.isPrimitive("HELLO")
F.isPrimitive(new String("HELLO"))
F.isPrimitive(new Number(123))
F.isPrimitive({})
F.isPrimitive([])
F.isPrimitive(()=>{})
License