nodekell
    TypeScript icon, indicating that this package has built-in type declarations

    2.11.4 • Public • Published

    nodekell

    Functional library for nodejs

    NPM Version NPM Downloads Build Status dependencies FOSSA Status DeepScan grade Codacy Badge

    Import Module

    // const F = require("nodekell");
    import * as F from "nodekell"

    Quick Example

    const v = await F.run(
        F.range(Infinity),//[0,1,2...]
        F.filter(e => e % 2 == 0), //[0,2,4...] 
        F.map(e => e + 1), //[1,3,5...]
        F.take(5), // [1,3,5,7,9]
        F.reduce((acc, e) => acc + e)); // 1+3+5+7+9
    console.log(v);//25
    const v = await F.run(
        F.repeat(2), //[2,2,2,..]
        F.map(e => e + 1), //[3,3,3...]
        F.take(5), // [3,3,3,3,3]
        F.distinct, // [3]
        F.collect); // generator to array
    console.log(v);//[3]

    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),//[0~9]
                F.filter(e => e % 2 == 0), //[0,2,4,6,8] 
                F.map(e => e + 1), //[1,3,5,7,9]
                F.reduce((acc, e) => acc + e)) // 1+3+5+7+9
    console.log(+ 1); // 25 + 1

    this expands to

    const v = await F.reduce((acc, e) => acc + e, // 1+3+5+7+9
                        F.map(e => e + 1, //[1,3,5,7,9]
                            F.filter(e => e % 2 == 0, //[0,2,4,6,8]
                                F.range(10)))); //[0~9]

    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(), //[1,2,3,4,5]
        F.reverse, //[5,4,3,2,1]
        F.collect); //generator to array
    const a = [1,5,4,3,2];
    const result = await rs(a);//call
    console.log(result); //[5,4,3,2,1]
    const double1 = F.pipe(
        F.map(e => e + e), //[2,4,6,8]
        F.collect);
    const a = [1,2,3,4];
    const r1 = await double1(a);
    console.log(r1); // [2,4,6,8]
    const double2 = F.pipe(
        t => t.map(e => e + e)); // Array.map
     
    const a = [1,2,3,4];
    const r2 = await double2(a); // return promise
    console.log(r2); // [2,4,6,8]

    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, //generator to array
        F.reverse, //[5,4,3,2,1]
        e => e.sort() //[1,2,3,4,5]
    );
    const a = [1,5,4,3,2];
    const result = await rs(a);//call
    console.log(result); //[5,4,3,2,1]
    const double1 = F.compose(
        F.collect,
        F.map(e => e + e) //[2,4,6,8]
    );
    const a = [1,2,3,4];
    const r1 = await double1(a);
    console.log(r1); // [2,4,6,8]
    const double2 = F.compose(
        t => t.map(e => e + e)); // Array.map
     
    const a = [1,2,3,4];
    const r2 = await double2(a); // return promise
    console.log(r2); // [2,4,6,8]

    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);//<- real call
    console.log(myAdd3); // print 6
    const myAdd = F.curry((a,b,c) => a + b + c);
    const r = myAdd(1,2,3); // <- real call
    console.log(r); // print 6

    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);
    }
    //print
    //2
    //4
    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);
    }
    //print 
    //2
    //4

    filterIndexed

    filter with loop counter

    const a = ["Apple", "Banana", "Orange", "Strawberry"];
    const filtered = F.filterIndexed((i, e) => {
        return e[i] === "a";
    }, a);
    //i => 0,1,2,3 
    //b[a]nana
    //or[a]nge
    //str[a]wberry
     
    for await (const e of filtered) {
        console.log(e);
    }
    //print
    //"Banana"
    //"Orange"
    //"Strawberry"

    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);
    }
    //print
    //1
    //3
    //5
    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);
    }
    //print 
    //1
    //3
    //5

    map

    const a = [1,2,3,4,5];
    for await (const e of F.map(e=> e * 2, a)) {
        console.log(e);
    }
    //print 2 4 6 8 10
    const v = await F.run([1,2,3,4,5],
                F.map(e => e + 1),
                F.collect);
    console.log(v);
    //print 2 3 4 5 6        

    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);
    }
    //print 
    //a0
    //b1
    //c2
    //d3
    //34

    take

    const a = [1,2,3,4,5];
    const t = F.take(3, a);
    console.log(await F.collect(t)); // print 1 2 3
    const v = await F.run(
        F.range(Infinity),
        F.take(2),
        F.collect
    );
    console.log(v); // print 0 1

    takeWhile

    const a = [1,2,3,1,2,3];
    const t = F.takeWhile(e => e < 3, a);
    console.log(await F.collect(t)); // print 1, 2

    fmap

    const a = [[1],[2],[3],[4],[5]];
    const f = F.fmap(e => e, a);
    console.log(await F.collect(f)); // print [1,2,3,4,5]
    const a = [ 
            [Promise.resolve(1)],
            Promise.resolve([2]),
            [3],
            [4],
            [5]];
    const f = F.fmap(e => e, a);
    console.log(await F.collect(f)); // print [1,2,3,4,5]

    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)); // print [1,2,3,4,5]

    dflat

    Similar to flat, but works recursively

    const r = F.dflat([[[1],[2]]],[[3]],[4]);
    const c = await F.collect(r);
    console.log(c);//print [1,2,3,4]
    const r = F.dflat("HELLO");
    const c = await F.collect(r);
    console.log(c);//print ["H","E","L","L","O"]

    reverse

    const a = [1,2,3,4,5];
    const t = F.reverse(a);
    console.log(await F.collect(t)); // print 5,4,3,2,1

    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); 
    // print 121

    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); 
    // print 
    // 0 'a'
    // 1 'b'
    // 2 'c'
    // 3 'd'
    // 4 'e'

    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);
    }
    //print
    //[1,6]
    //[2,7]
    //[4,9]
    //[5,0]

    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);
    }
    //print
    //[1,4,7]
    //[2,5,8]
    //[3,6,9]
    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);
    }
    //print
    //[1,4,7]
    //[2,5,8]

    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);
    }
    //print
    //[1,"a"]
    //[2,"b"]

    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);
    //print [12,15,18]

    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); // print [4, 5]
    const a = [1,2,3,4,5];
    const r = F.drop(Infinity, a)
    const result = await F.collect(r);
    console.log(result); // print []

    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); // print [1, 2]
    const a = [1,2,3,4,5];
    const r = F.dropLast(Infinity, a)
    const result = await F.collect(r);
    console.log(result); // print []

    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); // print [3,4,1]
    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); // print [3,4,1]

    emptyThen

    const v = await F.run(F.range(Infinity),
                F.take(0), // take 0 
                F.emptyThen([1,2,3,4,5]), // new array
                F.map(e => e + 1), // 2,3,4,5,6
                F.collect);
    console.log(v); // 2,3,4,5,6
    const v = await F.run(F.range(Infinity),
        F.take(0),// take 0
        F.emptyThen(()=> { return [1,2,3] }), // new array from function
        F.map(e => e + 1), // 2,3,4
        F.collect) 
    console.log(v);// 2,3,4
    const v = await F.run(F.range(Infinity),
        F.take(3), // [0,1,2]
        F.emptyThen(([9,9,9]),//not work
        F.map(e => e + 1), //[1,2,3]
        F.collect);
    console.log(v); //2,3,4

    distinct

    const a = [1,2,1,2,2,3];
    const r = F.distinct(a);
    const result = await F.collect(r);
    console.log(result); // print 1,2,3

    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);
    }
    //print
    //{num:1}
    //{num:2}

    distinctUntilChanged

    const a = [{num:1}, {num:1}, {num:2}];
    const r = F.distinctUntilChanged(a);
    for await (const e of r) {
        console.log(e);
    }
    //print
    //{ num: 1 }
    //{ num: 2 }
    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);
    }
    //print
    //1
    //2
    //3
    //4
    //5

    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);
    }
    //print
    //{ num: 1 }
    //{ num: 2 }
    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);
    }
    //print
    //1
    //2
    //3
    //4
    //5

    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);
    }
    //print 
    //hello
    //world

    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);
    // print
    // [{id:1, name:"foo", value:3},
    // {id:2, name:"bar", value:4}]

    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);
    //  print
    // [{id:1, name:"foo", value:3}]

    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);
    // print
    // [{id:1, name:"foo", value:3},
    // {id:2, name:"bar", value:4},
    // {id:3, name:"hoo"}]

    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);
    // print
    // [{id:1, name:"foo", value:3},
    // {id:1, name:"bar", value:3},
    // {id:1, name:"hoo", value:3}]

    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);
    //print
    //1
    //2
    //3
    //4
    //5
    //[2,3,4,5,6]
    const v = await F.run([1,2,3,4,5],
        F.then(iter => {
            return iter; //do nothing
        }),
        F.collect);
    console.log(v);
    // print
    // [1,2,3,4,5]

    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), //print and return Promise([1,2,3,4,5])
        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);
    }
    //print [1,2,3,4,5,6]
    const v = await F.run(
        F.concat([1,2,3],[4,5,6]),
        F.collect);
    console.log(v);
    //print [1,2,3,4,5,6]

    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);
    //print [0,1,3,6]
    const r = F.scanl((a, b) => a/b, 64, [4,2,1]);
    const r = await F.collect(s);
    console.log(r);
    //print [64,16,8,8]

    scanl1

    const s = F.scanl((a,b) => a + b, [1,2,3]);
    const r = await F.collect(s);
    console.log(r);
    //print [1,3,6]
    const r = F.scanl1((a, b) => a/b, [64,4,2,1]);
    const r = await F.collect(s);
    console.log(r);
    //print [64,16,8,8]

    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); //print [[1],[2],[3],[4],[5]]
    const b = F.buffer(2, [1,2,3,4,5]);
    const c = await F.collect(b);
    console.log(c); //print [[1,2],[3,4],[5]]

    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);
    //print 
    //2
    //3
    //4
    //5
    //6
    const a = [1,2,3,4,5];
    const p = F.peek(e=> e + 1, a)
    const result = await F.collect(p);
    console.log(result); //not change 
    //print [1,2,3,4,5]

    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);
    }
    // print "a", "b"
    const a = async function *() {
        yield [1, 2];
        yield [3, 4];
        yield [5, 6];
    };
    for await (const e of F.keys(a())) {
        console.log(e);
    }
    // print [1, 3, 5]s

    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);
    }
    // print
    // 1
    // 2
    const a = async function *() {
        yield [1, 2];
        yield [3, 4];
        yield [5, 6];
    };
    for await (const e of F.values(a())) {
        console.log(e);
    }
    // print
    // 2
    // 4

    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);
    }
    // print
    // 2
    // 3
    // 4
    const arr = [1, 2, 3, 4];
    const r = F.removeFirst((e) => e % 2 === 0, arr);
    for await (const e of r) {
        console.log(e);
    }
    // print
    // 1
    // 3
    // 4

    updateAt

    Update itererator to the index position

    const arr = [1,2,3,4,5];
    const u = F.updateAt(
        99, // update value
        0,  // index
        arr // iterator
    );
    for await (const e of u) {
        console.log(e);
    }
    //print
    //99
    //2
    //3
    //4
    //5

    updateFirst

    In itererator, update the first value that matches 2nd argument to 3rd argument.

    const arr = [1, 2, 3];
    const r = F.updateFirst(
        99, // update value
        1,  // find value
        arr);
    for await (const e of r) {
        console.log(e);
    }
    // print
    // 99
    // 2
    // 3

    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);
    //print
    //0
    //1
    //2
    F.parallel_set_fetch_count(200);
     
    await F.run(
        F.range(Infinity),
        F.pmap(async e =>{
            console.log(e);
            return e + 1;
        }), // fetch and execute first [0..199]
        F.take(1), // take 0 and execute 200. in pmap:[3..102]
        F.collect);
    //print
    //0
    //1
    //2
    //3
    //4
    //5
    //...
    //...
    //198
    //199
    //200

    pfilter

    Same as filter, but calls a fetch count of functions concurrently.

    useful for async function or return promise.

    //F.parallel_set_fetch_count(100);  default is 100
    const v = await F.run(
        F.range(Infinity),
        F.pfilter(async e =>{
            console.log(e);
     
            //somthing async work...
     
            return e % 2 === 0;
        }),// fetch and execute first [0..99]
        F.take(2),// take 2 and execute 100, 101, 102 in pmap:[3..102]
        F.collect);
    console.log(v);
    //print
    //1
    //2
    //3
    //...
    //...
    //99
    //[0,2]

    pmap

    Same as map, but calls a fetch count of functions concurrently.

    useful for async function or return promise.

    //F.parallel_set_fetch_count(100); default is 100
    const v = await F.run(
        F.range(Infinity),
        F.pmap(async e =>{
            console.log(e);
     
            //somthing async work...
     
            return e + 1;
        }), // fetch and execute first [0..99]
        F.take(2), // fetch 0, 1, excute 100, 101 in pmap:[2..101]
        F.collect);
    console.log(v);
    //print
    //0
    //1
    //2
    //...
    //...
    //99
    //100
    //101
    //[1,2]

    pfmap

    Same as fmap, but calls a fetch count of functions concurrently.

    useful for async function or return promise.

    // F.parallel_set_fetch_count(100); default is 100
    const v = await F.run(
        F.range(Infinity),  //0,1,2,...
        F.map(e=> [e]),     //[0],[1],[2]...
        F.pfmap(async e =>{
            console.log(e); //print [0] ...
     
            //somthing async work...
     
            e.push(42);     // [0,42],[1,42],[2,42]... 
            return e ;
        }),
        F.take(5),          //[0,42,1,42,2]
        F.collect);         //iterator to array
    console.log(v);
    //print
    //[0]
    //[1]
    //[2]
    //...
    //...
    //[99]
    //[0,42,1,42,2]

    pcalls

    1. 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);
    //print [1,2,3,4]
    1. call vaarg async functions
    /*like*/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); //print [1,2,3,4]

    reFind

    Use regular expression return first matching in str

    const r = F.reFind(/H(\d)/, "H1ello H2World");
    console.log(r); // print H1

    reFindSubmatch

    Use regular expression return first matching in str and groups

    const r = F.reFindSubmatch(/H(\d)/, "H1ello H2World");
    console.log(r[0]); // print H1
    console.log(r[1]); // print 1

    reFindAll

    Use regular expression return all matching in str

    const r = F.reFindAll(/H(\d)/, "H1ello H2World");
    console.log(r);
    //print ['H1', 'H2']

    reFindAllSubmatch

    Use regular expression return all matching in str and groups

    const r = F.reFindAllSubmatch(/H(\d)/, "H1ello H2World");
    console.log(r[0][0]); // print H1
    console.log(r[0][1]); // print 1
     
    console.log(r[1][0]); // print H2
    console.log(r[1][1]); // print 2

    range

    for (const e of F.range(10)) {
        console.log(e);
    }
    //print 0 ~ 9
     
    for (const e of F.range(10, 0, -1)) {
        console.log(e);
    }
    //print 10 ~ 1

    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);
    }
    //print 1,2,3,4,5
    const a = new Map([[1,2],[3,4]]);
    for await(const e of F.seq(a)) {
        console.log(e);
        //print 
        //[1,2]
        //[3,4]
    }

    repeat

    const r = F.repeat(3);
    for await(const e of r) {
        console.log(e);
    }
    //print 
    //3
    //3
    //3
    //....
    const v = await F.run(
        F.repeat(1), //[1,1,1....]
        F.map(e => e + 1), //[2,2,2....]
        F.take(5), //[2,2,2,2,2]
        F.collect); //generator => array
    console.log(v);
    //print [2,2,2,2,2]
    const r = F.repeat(()=>{return 3;});
    for await(const e of r) {
        console.log(e);
    }
    //print 
    //3
    //3
    //3
    //....
    const r = F.repeat(3, 5);
    for await(const e of r) {
        console.log(e);
    }
    //print 
    //5
    //5
    //5

    rangeInterval

    first argument is set to the repeat interval

    for await (const e of F.rangeInterval(100, 5)) {
        console.log(e);
    }
    //print
    // [sleep 100]
    // 0
    // [sleep 100]
    // 1
    // [sleep 100]
    // 2
    // [sleep 100]
    // 3
    // [sleep 100]
    // 4
    // [sleep 100]
    for await (const e of F.rangeInterval(100, 5, 0, -1)) {
        console.log(e);
    }
    //print
    // [sleep 100]
    // 5
    // [sleep 100]
    // 4
    // [sleep 100]
    // 3
    // [sleep 100]
    // 2
    // [sleep 100]
    // 1
    // [sleep 100]

    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);
    //print 
    //[1,2,3,4,5]
    const fibo = (a) => [a[1], a[0] + a[1]];
    const r = await F.run(
        F.iterate(fibo, [0, 1]),//[0, 1], [1, 1], [1, 2], [2, 3] ...
        F.map(F.head),//[0,1,1,2 ... 
        F.take(10),//[0,1,1,2,3,5,8,13,21,34]
        F.collect);//generator to array
    console.log(r);
    //print
    //[0,1,1,2,3,5,8,13,21,34]

    enumerate

    like python enumerate

    const arr = ["a", "b", "c", "d", "e"];
    for await (const [i, e] of F.enumerate(arr)) {
       console.log(i, e);
    }
    //print
    // 0 'a'
    // 1 'b'
    // 2 'c'
    // 3 'd'
    // 4 'e'

    foldl

    const a = [1,2,3,4,5];
    const sum = await F.foldl((acc, e) => acc + e, 0, a); 
    console.log(sum); // print 15
    const a = ["w","o","r","l","d"];
    const sum = await F.foldl((acc, e) => acc + e, "hello", a); 
    console.log(sum); // print "helloworld"

    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); // print 15;

    reduce

    same as foldl1

    const a = [1,2,3,4,5];
    const sum = await F.reduce((acc, e) => acc + e, a); 
    console.log(sum); // print 15;

    juxtA

    const a = await F.juxtA([Math.max, Math.min], [1,2,3,4,5]);
    console.log(a);
    //print [5,1]
    const a = await F.juxtA([Math.max, Math.min], []);
    console.log(a);
    //print [undefined, undefined]

    foldr

    const arr = [1,2,3,4,5];
    const r = await F.foldr((a, b) => a + b, 0, arr);
    console.log(r); // print 15
    const arr = [64,2,1];
    const r = await F.foldr((a, b) => a / b, 1, arr);
    console.log(r); // print 32
    const arr = ["1","2","3","4"];
    const r = await F.foldr((a, b) => a + b, "5", arr);
    console.log(r); // print 12345

    foldr1

    const arr = [1,2,3,4,5];
    const r = await F.foldr1((a, b) => a + b, 0, arr);
    console.log(r); // print 15
    const arr = [64,2,1];
    const r = await F.foldr1((a, b) => a / b, arr);
    console.log(r); // print 32
    const arr = ["1","2","3","4","5"];
    const r = await F.foldr1((a, b) => a + b, arr);
    console.log(r); // print 12345

    collect

    iterator or asyncIterator to Array

    const mapped = F.map(e => e + 1, a); 
    console.log(mapped); // print asyncGenerator
    const collected = await F.collect(mapped);
    console.log(collected); //print [2,3,4,5,6]
    const v = await F.run(
        F.range(Infinity),//[0,1,2....]
        F.filter(e => (% 3) === 0), //[0,3,6...] 
        F.map(e => e + 1), //[1,4,7...]
        F.take(5), // generator([1,4,7,10,13])
        F.collect);  // generator => array
    console.log(v); //[1,4,7,10,13]

    collectMap

    const a = [[1,2],[3,4]];
    const m = await F.collectMap(a); // new Map([[1,2],[3,4]])
    for(const [k,v] of m) {
        console.log(k, v);
    }
    //print 
    //1 2
    //3 4

    collectSet

    const a = [1,2,3,1,2,3];
    const m = await F.collectSet(a); //new Set([1,2,3])
    for(const e of m) {
        console.log(e);
    }
    //print 
    //1
    //2
    //3
    const a = "hello world";
    const m = await F.collectSet(a); //new Set("helo wrd")
    for(const e of m) {
        console.log(e);
    }
    //print 
    //helo wrd

    collectObject

    const a = [[1,2],[3,4]];
    const m = await F.collectObject(a); // {1:2,3:4}
    console.log(m);
    //print { '1': 2, '3': 4 }

    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); 
    //print Int8Array [ 1, 2, 3, 4 ]

    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); 
    //print Int16Array [ 1, 2, 3, 4 ]

    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); 
    //print Int32Array [ 1, 2, 3, 4 ]

    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); 
    //print Uint8Array [ 1, 2, 3, 4 ]

    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); 
    //print Uint16Array [ 1, 2, 3, 4 ]

    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); 
    //print Uint32Array [ 1, 2, 3, 4 ]

    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); 
    //print Uint32Array [ 1, 2, 3, 4 ]

    maxBy

    const a = [10,9,8,7];
    const r = await F.maxBy(e => e, a);
    console.log(r); // print 10;
    const a = [1,10,9,8,7,11];
    const r = await F.maxBy(e => Math.floor(e/10), a) //compare [0,1,0,0,0,1]
    console.log(r); // print 10

    minBy

    const a = [0,10,9,8,7];
    const r = await F.minBy(e => e, a);
    console.log(r); // print 0
    const a = [7,10,9,8,1,11];
    const r = await F.minBy(e => Math.floor(e/10), a) //compare [0,1,0,0,0,1]
    console.log(r); // 7

    max

    const a = [Promise.resolve(10),9,8,7];
    const r = await F.max(a);
    console.log(r);
    //print 10

    min

    const a = [10,9,8,Promise.resolve(7)];
    const r = await F.min(a);
    console.log(r);
    //print 7

    some

    const a = [1,2,3,4,5];
    const r = await F.some(e=> e % 2 == 0, a); //found '2' return
    console.log(r); // true
    const r = await F.run(
        F.range(Infinity), //[0...Infinity]
        F.some(e=> Promise.resolve(> 100)) // found '101' return
    );
    console.log(r); // true

    every

    const a = [1,2,3,4,5];
    const r = await F.every(e=> e  >= 0, a); // all elem >= 0 return true
    console.log(r); // true
    const a = [1,2,3,4,5];
    const r = await F.every(e=> Promise.resolve(< 3), a); 
    //1 ok, 2 ok, 3 no return false
    console.log(r); // false

    count

    const a = [1,2,3,4,5];
    const n = await F.count(a);
    console.log(n); // print 5

    sum

    const a = [1,2,3,4,5];
    const n = await F.sum(a);
    console.log(n); // print 15
    const a = "abcde";
    const n = await F.sum(a);
    console.log(n); // print abcde

    average

    const a = [1,2,3,4,5];
    const s = await F.average(a);
    console.log(s); // print 3
    const a = [1.0,2.0,3.0,4.0,5.5];
    const s = await F.average(a)
    console.log(s); //print 3.1

    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},
    ];
    //returns new Map(... )
    const r = await F.groupBy(e => e.type, a);
    console.log(r.get("tea"));
    //print [ { type: 'tea', price: 1 }, { type: 'tea', price: 2 } ]
    console.log(r.get("phone"));
    //print [ { type: 'phone', price: 3 }, { type: 'phone', price: 4 } ]

    orderBy

    const a = [{ year: 1990 }, { year: 2005 }, { year: 1958 }];
     
    const ASC = 'ASC'; // or 'asc'
    const DESC = 'desc'; // or '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);
    // [{ year: 1958 }, { year: 1990 }, { year: 2005 }]
    await F.collect(sortedByDESC1);
    // [{ year: 2005 }, { year: 1990 }, { year: 1958 }]
    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);
    // [2, 3, 3, 6, 7, 10, 13, 14, 16, 17, 20, 21, 22, 23]
    await F.collect(sortedbyDESC);
    // [23, 22, 21, 20, 17, 16, 14, 13, 10, 7, 6, 3, 3, 2]
    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('')]);
    // ['  BCHaekklloorrrssuy']
    await F.collect(sortedByDESC).then(e => [e.join('')]);
    // ['yussrrroollkkeaHCB  ']

    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);
    // [2, 3, 3, 6, 7, 10, 13, 14, 16, 17, 20, 21, 22, 23]
    await F.collect(sortedbyDESC);
    // [23, 22, 21, 20, 17, 16, 14, 13, 10, 7, 6, 3, 3, 2]
    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('')]);
    // ['  BCHaekklloorrrssuy']
    await F.collect(sortedByDESC).then(e => [e.join('')]);
    // ['yussrrroollkkeaHCB  ']

    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); // print [1,2,3,4,5]

    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); // print [1,2,3,4,5]

    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);
    //print
    //Map { 1 => 2, 2 => 1, 3 => 1, 4 => 1, 5 => 2 }

    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);
    //print
    //Map { 
    //      1 => 2, 
    //      2 => 1, 
    //      3 => 1, 
    //      4 => 1, 
    //      5 => 2 }
    const obj = [{a:1},{a:2},{a:1},{a:3}];
    const r = await F.frequenciesBy(e => e.a, obj);
    console.log(r);
    //print
    //Map { 
    //      1 => 2, 
    //      2 => 1, 
    //      3 => 1 }

    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);
    //print Map { 1 => 2, 2 => 4, 3 => 6 }
    const arr1 = [1, 2, 3];
    const m1 = await F.associateBy(e => e + 1, arr1);
    console.log(m1);
    //print Map { 2 => 2, 3 => 3, 4 => 4 

    block

    1. await promise
    2. Fetch all the elements of type iterator. When an element returns a promise, it waits for it to finish.
    3. 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); 
    //print true
    const value = [1, 2];
    F.match(value,
        [0, 1], () => console.log("match [0, 1]"),
        F._, () => console.log("match F._")
    );
    //print 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); // print [1, 3]
     
    const r1 = await juxtO(["A","C"], {});
    console.log(r1); // print [undefined, undefined] 
     
    const r2 = await juxtO(["A","C"],  new Map([["A", 1], ["B", 2], ["C", 3]]));
    console.log(r2); // print [1,2]

    sleep

    like other language

    const beginDate = Date.now();
    await F.sleep(1000);
    const endDate = Date.now();
    console.log(endDate - beginDate); // print 1009

    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)); //print 1
    console.log(await F.head(a)); //print 1
    const a = F.seq([10,9,8,7]); // make generator
    console.log(await F.head(a)); //print 9
    console.log(await F.head(a)); //print 8
    console.log(await F.head(a)); //print 7
    const a = [];
    try{
        await F.head(a);
    }catch(e) {
        console.log(e);
    } 
    //print empty iter 

    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)); // print 2 3 4 5
    const a = F.seq([10,9,8,7]); //make generator
    for await (const e of F.tail(a)){
        console.log(e);
    }
    for await (const e of a) {
        //a is empty...
        console.log("a is empty");
    }
    //print 
    //9
    //8
    //7

    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!");
    });
    ///print 
    //WORK!
    // 1 sec 
    //WORK!
    // 1 sec
    //... 

    timeout

    @changed iterator timeout use withTimeout instead.

    const foo = async () => {
        await F.sleep(1);/*something work*/
        return 1;
    };
    const v = await F.timeout(40, foo());
    console.log(v);
    //print 1;
    try{
        await F.timeout(40, async ()=>{
            await F.sleep(1000);
        });
    } catch(e) {
       console.log(e); 
    }
    //print
    //timeout error
    //callstack...

    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);
    //print 
    //timeout error
    //callstack...
    //[1,2,3,4,5,6]
    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);
    }
    //print 
    //timeout error
    //callstack....

    isNil

    return false null, undefined, NaN true otherwise

    console.log(F.isNil(NaN)); // true
    console.log(F.isNil(undefined)); //true
    console.log(F.isNil(null)); //true
    console.log(F.isNil("null")); // false 
    console.log(F.isNil("NaN")); //false
    console.log(F.isNil(0)); // false
    console.log(F.isNil(false)); // false
    console.log(F.isNil([])); // false
    console.log(F.isNil({})); // false

    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); // "tt"
    const r = await F.cond( 
        Promise.resolve(false), "ff",
        Promise.resolve(true), "tt",
        F.otherwise, "oo"
    );
    console.log(r); // "tt"

    otherwise

    if (F.otherwise) {
        console.log("WORK!");
    }
    if (F.otherwise()) {
        console.log("WORK!");
    }
    //print 
    //WORK!
    //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)); //print hello
    const m = new Map([
        ["name", "hello map"]
    ]);
    console.log(F.get("name", m)); //print hello map
    console.log(F.get("size", m)); //print 1

    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); // print hello map
     
    const r1 = F.getOrElse("foo", "world", m);
    console.log(r1); // print world

    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)); //print hello

    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); // arr[0]
    console.log(r0); // print 1
     
    const r1 = F.propOrElse("5", 100, arr); // arr[100]
    console.log(r1); // print 100

    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); //print true
    const r = F.has("hello", new Map([["hello","world"]]));
    console.log(r); //print true
    const r = F.has("size", new Map());
    console.log(r); //print true

    find

    const arr = [{a:"a1"}, {b:"a2"}, {a:"a3"}];
    const r = await F.find(e => "a" in e , arr);
    console.log(r); // print {a:"a1"}
    const arr = [{a:"a1"}, {b:"a2"}, {a:"a3"}];
    const r = await F.find(e => "hello" in e , arr);
    console.log(r); // print undefined

    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); // print {a:"a1"}
    const arr = [{a:"a1"}, {b:"a2"}, {a:"a3"}];
    const r = await F.find(e => "hello" in e , arr);
    console.log(r); // print undefined

    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); // print {a:"a3"}
    const arr = [{a:"a1"}, {b:"a2"}, {a:"a3"}];
    const r = await F.findLast(e => "hello" in e , arr);
    console.log(r); // print undefined

    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(); 
    //print
    //callOnce
    const beginTime = Date.now();
    const memFibo = F.memoize(async (n) => {
        if (=== 0) return 0;
        if (=== 1) return 1;
        return await memFibo(- 1) + await memFibo(- 2);
    });
    console.log(await memFibo(30));
    console.log(`Elapsed time:${Date.now()-beginTime}msec`);
    // print
    // 832040
    // Elapsed time:1msec

    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(); 
    //print
    //callOnce
    const beginTime = Date.now();
    const memFibo = F.memoizeBy(F.identity, async (n) => {
        if (=== 0) return 0;
        if (=== 1) return 1;
        return await memFibo(- 1) + await memFibo(- 2);
    });
    console.log(await memFibo(30));
    console.log(`Elapsed time:${Date.now()-beginTime}msec`);
    // print
    // 832040
    // Elapsed time:1msec

    random

    internally use crypto.randomBytes

    const r0 = F.random(); // print 0 ~ 4294967295
    const r1 = F.random(10); // print 0 ~ 9
    const r2 = F.random(1, 42); // print 1 ~ 41, maximum range: 4294967295 

    equals

    compares deep strict equals

    const a = 1;
    F.equals(a, 1); // true
    F.equals(a, 0); // false
    const o = {a:1};
    F.equals({a:1}, o); // true
    F.equals(NaN, NaN); // true
    F.equals([0,1], [0,1]); // true

    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);
    //print [5,3,2,1,4]
    const a = function*() {
        yield 1;
        yield 2;
        yield 3;
        yield 4;
        yield 5;
    };
    const sf = await F.shuffle(a()); // await required
    console.log(sf);
    //print [5,3,2,1,4];
    const a = async function*() {
        yield 1;
        yield 2;
        yield 3;
        yield 4;
        yield 5;
    };
    const sf = await F.shuffle(a()); // await required
    console.log(sf);
    //print [5,3,2,1,4];

    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); //print 1 ~ 6 random
    const r = await F.sample(F.range(100));
    console.log(r); //print 0 ~ 100 random 

    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]")
    );
     
    //print match [1, any]
    const value = [1, 2];
    const res = F.match(value,
        [0, 1], () => 3,
        [1, 2], () => 4
    );
    console.log("match returns " + res);
    //print match 4

    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(); // print hello javascript
    sayHelloWithDefault("leanne"); // print hello 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));
    //print { a: 1, b: 1 };

    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));
    //print { a: 1, b: 1, c: 1 };

    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); // print Map { 1 => 2, 3 => 4, 5 => 6, 7 => 8 }
     
    const m3 = new Map([[1, 2], [3, 4]]);
    const o1 = { 5: 6, 7: 8 };
    const r2 = await F.mergeMap(m3, o1);
    console.log(r2); // print Map { 1 => 2, 3 => 4, '5' => 6, '7' => 8 }

    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]