@keepzen/fp
v1.0.11
Published
Function Light Programe for nodejs
Downloads
21
Readme
id: (any)=>any
The idempotent function.
Parameters
v
any
Returns any the parameter v
.
unary: (fun)=>Function
Convert fun
to an unary function.
Parameters
fun
Returns Function
binding: (fun,...args)=>Function
Biding function fun
with arguments fellow it.
Parameters
fun
Function This is the function whos parameters you want to bind.args
…*any* The values you bind to the parameters offun
.
Return Function.
The length of return function is fun.length - args.length
,
if args
are all normal values, when args
includes placeholder _
,
the length will add the count of placeholders.
Examples
const binding = require('./binding');
const _ = binding.placeHolder;
const fn = (a, b, c, d) => a + b + c + d;
test("binding()", () => {
let bindFn = binding(fn, "1", _, "3");
expect(typeof bindFn).toBe('function');
expect(bindFn.length).toBe(fn.length - 2);
expect(bindFn(2, "a")).toBe('123a');
let bindFn2 = binding(bindFn, _, "a");
expect(bindFn2(2)).toBe(bindFn(2, "a"));
let z = jest.fn(fn);
let bindFn3 = binding(z, 1, 2, 3, 4, 5);
expect(bindFn3.length).toBe(0);
expect(bindFn3()).toBe(1 + 2 + 3 + 4);
expect(z).toHaveBeenCalledWith(1, 2, 3, 4, 5);
console.log(bindFn2.toString());
})
bindidng.placeHolder: Symbol
The place holder that can be use zero or manny times as element of args
in binding(fun,...args)
.
compose: (...funs)=>Function
Compose functions fns
to make a new function.
Parameters
fns
Function The functions you want to compose them to be one.
Returns Function
Examples
const { compose, pipe } = require('./compose');
const g = jest.fn((a, b) => a + b);
const f = jest.fn(c => c + 1);
test('compose(f,g)', () => {
const z = compose(f, g);
expect(typeof z).toBe('function');
expect(z.length).toBe(g.length);
expect(z(1, 2, 3)).toBe(1 + 2 + 1);
expect(g).toHaveBeenCalledWith(1, 2, 3);
expect(f).toHaveBeenCalledWith(3);
})
pipe: (...funs)=>Function
pipe
is like the compose
but reverse the execute order.
It is differtne with pipable
. pipable
make a functor.
Parameters
fns
…Function
Returns Function
Examples
const { compose, pipe } = require('./compose');
const g = jest.fn((a, b) => a + b);
const f = jest.fn(c => c + 1);
test('compose(f,g)', () => {
const z = compose(f, g);
expect(typeof z).toBe('function');
expect(z.length).toBe(g.length);
expect(z(1, 2, 3)).toBe(1 + 2 + 1);
expect(g).toHaveBeenCalledWith(1, 2, 3);
expect(f).toHaveBeenCalledWith(3);
})
test('pipe(g,f)', () => {
const z = pipe(g, f);
expect(typeof z).toBe('function');
expect(z.length).toBe(g.length);
expect(z(1, 2, 3)).toBe(1 + 2 + 1);
expect(g).toHaveBeenCalledWith(1, 2, 3);
expect(f).toHaveBeenCalledWith(3);
console.log(z.name);
})
m2f: (method)=>Function
Convert a method to a function.
If you have a function fn
you can attch it to a object obj
like
obj.fn=fn
, so the this
in fn
now is obj
.
But how do you do if you want use a method as a function? Like sort arrays with a fixed way?
m2f
is use to help you for this.
Parameters
method
Function The method you want covert to a function.
Returns Function.
The return function do same as md
, but add this
as the first parameter.
Examples
const m2f = require('./m2f');
test('metholdToFunction()', () => {
const join = m2f([].join);
expect(typeof join).toBe(`function`);
expect(join([1, 2], ",")).toBe([1, 2].join(","));
expect(join.length).toBe([].join.length + 1);
})
deepCopy: (any[,{freeze}])=>any
Deep copy the value
.
Parameters
v
any$1
Object (optional, default{}
)$1.freeze
(optional, defaultfalse
)
Returns a new deep Copyed Object.
Examples
const deepCopy = require('./deep-copy');
test('deepCopy()', () => {
expect(deepCopy(1)).toBe(1);
expect(deepCopy(true)).toBe(true);
let fn = jest.fn();
expect(deepCopy(fn)).toBe(fn);
let a = [];
a.push(1, 3);
a.push(a)
let aCopy = deepCopy(a);
expect(aCopy[2]).toBe(aCopy);
let b = { a, v: 1 };
a.push(b);
let bCopy = deepCopy(b);
console.log(bCopy);
expect(bCopy === bCopy.a[3]).toBe(true);
})
constant: (any)=>()=>any
Give a value, get a function, which always return freezen deep copy of the given value.
If you just want get a immutable copy, just use
deepCopy(value,{freeze:true})
.
Parameters
value
any
Returns Function : ()=>freezenDeepCopyOfValue
Pipable
Note:This is the package of @keepzen/pipe.js
, and in package of @keepzen/fp
rexport
as Pipable
. So the snippets in this section, Pipe
, pipe
, from
, and -
are all in namespace of Pipable
.
Make a pipable
Pipable is a object, which have a method named .pipe(fun,...args)
.
You can get a new pipable object as fellow ways:
const {
Pipe,
pipe,
from,
_
} = require('./pipe.js')
test('make pipable', () => {
const properties = ['valueOf', 'pipe', 'map', "promise_rescue"].sort();
const keys = Object.keys.bind(Object);
expect(keys(Pipe(1)).sort()).toMatchObject(properties);
expect(keys(pipe(1)).sort()).toMatchObject(properties);
expect(keys(from(1)).sort()).toMatchObject(properties);
expect(keys(from(1).pipe(a => a + 1)).sort()).toMatchObject(properties);
})
As then snippet showed, a pipable
object have methods as fellow:
pipable.valueOf()
:Get the
v
you want to pipe to other function.So
pipe(a).valueOf() === a
is alwaystrue
:test('pipe(any).valueOf() == any', () => { expect(pipe(1).valueOf() == 1).toBe(true) expect(pipe("hello").valueOf() == "hello").toBe(true); expect(pipe(true).valueOf() == true).toBe(true); expect(pipe(false).valueOf() == false).toBe(true); let str = new String('Hello'); expect(pipe(str).valueOf() == str).toBe(true); expect(pipe(null).valueOf() == null).toBe(true); expect(pipe(undefined).valueOf() == undefined).toBe(true); let a = { hello: "a" }; expect(pipe(a).valueOf() == a).toBe(true) })
If a
is primary type but neither null
nor undefined
then pipe(a) == a
is true.
test('pipe(primary) == primary', () => {
expect(pipe(1) == 1).toBe(true)
expect(pipe("hello") == "hello").toBe(true);
expect(pipe(true) == true).toBe(true);
expect(pipe(false) == false).toBe(true);
let str = new String('Hello')
expect(pipe(str) == str).toBe(false);
expect(pipe(null) == null).toBe(false);
expect(pipe(undefined) == undefined).toBe(false);
let a = { hello: "a" };
expect(pipe(a) == a).toBe(false);
})
pipable.pipe(fun,...args)
: Return a pipable object.fun
is a function,args
are the rest arguments you want pipe tofun
.If
args
do not included placeholder_
,fun
will be called asfun(...[v,...args])
.If
args
included one and only one placeholder_
,pipable.valueOf()
will instead of the placehoder, andfun
will be called asfun(...args)
.
pipable.map(fun,...args)
:pipable.map
is the alias ofpipable.pipe
.pipable.promise_rescue(fun,...args)
: return a new pipable object.- when the
pipable.vlaueOf()
is a promise and the promise is reject, the reject reason will pipe tofun
. - when
pipeable.valueOf()
is not a promise,fun
will been skiped and return copy ofpipable
.
- when the
Use placeholder set which argument of fun
take the piped value
test('pipe with placeholder', () => {
let fn = jest.fn((a, b, c) => a + b + c);
let z = pipe('a').pipe(fn, 'b', 'c');
expect(fn).not.toHaveBeenCalled();
expect(z == 'abc').toBe(true);
expect(fn).toBeCalledWith('a', 'b', 'c');
z = pipe("2").pipe(fn, "1", _, "3");
expect(z == '123').toBe(true);
expect(fn).toBeCalledWith('1', '2', '3');
z = pipe('e').pipe(fn, 'a', 'b', 'c', 'd', _);
expect(z == 'abc');
expect(fn).toHaveBeenLastCalledWith('a', 'b', 'c', 'd', 'e');
})
pipable.pipe(fun,...args)
keep pipable
object immutable.
pipable.pipe(fn,...args)
will return a new pipable object,don't change the old one.
test('pipable is independ', () => {
let a = 1;
let fn1 = jest.fn(a => a + 1);
let fn2 = jest.fn((b, c) => b + c);
let pipable0 = pipe(a);
let pipable1 = pipable0.pipe(fn1);
expect(pipable1 == a + 1).toBe(true);
expect(pipable0.valueOf()).toBe(a);
let pipable2 = pipable1.pipe(fn2, 'c');
expect(pipable2 == '2c').toBe(true);
expect(pipable1.valueOf()).toBe(a + 1);
})
pipable.pipe(fn,...args)
is lazy
Call pipeable.pipe(fn,...args)
do not call fn
,
but pipable.valueOf()
will call the fn
if there have one.
As fellow show:
test(`pipable is layze`, () => {
const fn = jest.fn(a => a + 1);
let pipable0 = pipe(1);
let ret = pipable0.pipe(fn).pipe(fn).pipe(fn);
expect(fn).not.toHaveBeenCalled();
expect(ret.valueOf()).toBe(1 + 1 + 1 + 1);
expect(fn.mock.calls).toMatchObject([[1], [2], [3]]);
})
pipable<Promise>.pipe(fn,...args)
If the value of a pipable is a Promise
,
pipable.pipe(fn)
pipe the resolve value of the promise to fn
,
and return a new promise pipable.
Examaples
test('pipe promise resolve ', (done) => {
let a = from(Promise.resolve(1));
expect(a.valueOf()).toBeInstanceOf(Promise);
let fn = jest.fn(a => a + 1);
let ret = a.pipe(fn).
promise_rescue(fn).//skip
pipe(fn).valueOf();
expect(ret).toBeInstanceOf(Promise);
ret.then(() => {
expect(fn.mock.calls).toMatchObject([[1], [2]]);
done();
});
})
pipable<Promise>.promise_rescue
:
Return a new pipable.
If value of pipable<Promise>
is reject, this method can rescue from the error.
test('pipe promise reject', (done) => {
let a = from(Promise.reject('hello'));
let fn1 = jest.fn(a => 'fn1');
let fn2 = jest.fn(a => 'fn2');
let fn3 = jest.fn(a => "fn3");
let promise = a.pipe(fn1).//skip
promise_rescue(fn2).//call
pipe(fn3).valueOf();
expect(promise).toBeInstanceOf(Promise);
promise.then(
(a) => {
expect(fn1).not.toHaveBeenCalled();
expect(fn2).toHaveBeenCalledWith('hello');
expect(fn3).toHaveBeenCalledWith('fn2');
expect(a).toBe('fn3');
done();
},
(error) => {
console.error(error);
expect('not run to here').toBe('but it is here');
}
)
})
not: not(fn)=>Function
Negative fun
.
If fun
is a predicater, return a new negative predicater.
If fun
is a compare function, return the negative compare function.
Parameters
fun
Function :~(v,…args)=>Boolean|Number~
Returns Function other_fun: (v,...args)=>Boolean|Number
Examples
const not = require('./not');
test('not(p)', () => {
let p = n => n % 2 == 0;
expect(not(p)(2)).toBe(!p(2));
expect(not(p)(1)).toBe(!p(1));
expect(not((a, b) => a - b)(1, 2)).toBe(2 - 1);
})
selectWith: predicate=>array=>Array
select some array with predicate
.
Support there is an array
include value v
, and predicate(v)
is true,
then select(array)
will include v
.
Parameters
predicate
Function (v,index)=>Boolean;
Returns Function select: (array)=>array
Examples
let array = [1, 2, 3, 4];
let arrayb = [5, 6, 7, 8];
const isOlder = d => d % 2 == 0;
test('selectWith(fun,array)', () => {
const selectOld = selectWith(isOlder);
expect(selectOld(array)).toMatchObject([2, 4]);
expect(selectOld(arrayb)).toMatchObject([6, 8]);
rejectWith: predicate=>array=>Array
Reject some array with predicate
.
Support there is an array
include value v
,and predicate(v)
is true,
then reject(array)
will not include v
.
Parameters
predicate
Function : (v,index)=>Boolean;
Returns Function reject:(array)=>array
test('rejectWith(isOlder)', () => {
const rejectOlder = rejectWith(isOlder);
expect(rejectOlder(array)).toMatchObject([1, 3]);
expect(rejectOlder(arrayb)).toMatchObject([5, 7]);
})
orderWith: ~(compare[,{asc}])=>array=>Array
Order a array with a compare
function.
When asc
is true
, sort value in ascending order else in descending.
For compare(a,b)
, in asc order,
if you want a
in front of b
, return a negative number;
if your want b
in front of a
return a positive number;
else you do not care which first return zero.
Parameters
compare
Function :~(a,b)=>Boolean~ (optional, default(a,b)=>a-b
)$1
Object (optional, default{}
)$1.asc
(optional, defaulttrue
)
Returns Function order:(array)=>array
Examples
test('orderWith(fun)', () => {
let sortByZ = orderWith((a, b) => a.z - b.z);
let array = [{ a: 1, z: 2 }, { a: 2, z: 1 }, { a: 3, z: -1 }];
let first = array[0];
let ret = sortByZ(array);
expect(ret).toMatchObject([{ a: 3, z: -1 }, { a: 2, z: 1 }, { a: 1, z: 2 }]);
expect(ret[2]).toBe(first)
expect(array[0]).toBe(first);
});
test('orderWith(fun,{asc=false})', () => {
let sortByZ = orderWith((a, b) => a.z - b.z, { asc: false });
let array = [{ a: 1, z: 2 }, { a: 2, z: 1 }, { a: 3, z: -1 }];
let ret = sortByZ(array);
expect(ret).toMatchObject(array);
expect(ret).not.toBe(array);
expect(ret[0]).toBe(array[0]);
});
reverse: (array)=>Array
Get a reversed new the array from array
.
Parameters
array
Array
Returns Array
Examples
test('reverse(array)', () => {
let array = [1, 2, 3, 4];
expect(reverse(array)).toMatchObject([4, 3, 2, 1]);
expect(array).toMatchObject([1, 2, 3, 4]);
})
zip: (aIterable,arrayLikly)=>Array<Array(2)>
Zip arrays a1
and a2
to an array of array.
Parameters
Returns Array Array<Array(2)>
Examples
test('zip(a1,a2)', () => {
const a1 = [1, 2, 3, 4];
const a2 = ['one', 'two', 'three'];
const ret1 = zip(a1, a2);
expect(ret1).toMatchObject([[1, 'one'], [2, 'two'], [3, 'three'], [4, undefined]]);
expect(zip(a2, a1)).toMatchObject([['one', 1], ['two', 2], ['three', 3]]);
})
every: (fun,iterable)=>boolean
Check is every
element in iteratble
satisfy contiontion fun
.
If iterable
is empty, return true
. See more at
here;
Parameters
fun
Function :~(element[,index,array])~iterable
Iterable
Returns any boolean
Examples
test('every(funp,arrayLikly)', () => {
expect(every(positive, [1, 2, 3, 4])).toBe(true);
expect(every(positive, [1, 2, -1, 3, 4])).toBe(false)
expect(every(positive, [])).toBe(true)
})
all: (fun,iterable)=>boolean
Check is all
element in iteratble
satisfy contiontion fun
.
This is similarity as every but if iterable
is empty, return false
.
Parameters
fun
Function :(element[,index,array])=>boolean
iteratable
Iterable
Examples
const positive = a => a > 0;
test('all(funp,arrayLike)', () => {
expect(all(positive, [1, 2, 3, 4])).toBe(true);
expect(all(positive, [1, 2, -1, 3, 4])).toBe(false)
expect(all(positive, [])).toBe(false)
})
every: (fun,iterable)=>boolean
Similarity as , but if iterable
is empty, return true
.
any: (fun,iterable)=>boolean
Check is some
element in iterable
satisfy contiontion fun
.
Parameters
fun
Function :(element[,index,array])=>boolean
iterable
Iterable
Examples
test('any(funp,arrayLikly)', () => {
expect(any(positive, [-1, -2, -3, 4])).toBe(true);
expect(any(positive, [-1, -2, -3, -4])).toBe(false);
expect(any(positive, [])).toBe(false);
expect(any(positive, [0])).toBe(false);
expect(any(positive, [+0])).toBe(false);
expect(any(positive, [-0])).toBe(false);
})
some: (fun,iterable)=>boaolean
Alias of .