JFP

The Javascript Function Processor

Types

Predicates

Core

Math

Array

Object

Signatures

JFP is enforced with Signet types and function signatures. Signature metadata can be accessed via the signature property. All type signature information presented in the documentation reflects the Signet signatures attached to the functions.

j.isTypeOf.signature; // string => * => boolean
j.slice.signature; // index => array<*> => array<*>

Types

enforce

var add = j.enforce('number, number => number', function add (a, b) { return a + b; });

either

j.either('number')(5)(0); // 0
j.either('number')(5)('foo'); // 5

either built-ins

JFP provides several pre-loaded either type functions both for speed and to help keep your code slim and trim

isTypeOf

j.isTypeOf('string')(5); // false
j.isTypeOf('nil')(j.nil); // true

maybe

j.maybe('string')('foo'); // 'foo'
j.maybe('number')('foo'); // j.nil

function isEven (x) {
    return j.isTypeOf('number')(x) && x % 2 === 0;
}

j.maybe(isEven)(5); // nill
j.maybe(isEven)(5); // nill

maybe built-ins

JFP provides a pre-loaded maybe defined type function both for speed and to help keep your code slim and trim

setJfpTypes

var signetFactory = require('signet');

var signet = setJfpTypes(signetFactory());

sign

var add = j.sign('number, number => number', function add (a, b) { return a + b; });

typeChain

typeChain('boundedInt'); // * -> number -> int -> boundedInt
typeChain('array'); // * -> object -> array

Type List

Predicates

and

j.and(true, true); // true
j.and(true, false); // false

equal

j.equal(5, 5); // true;
j.equal(5, 7); // false;
j.equal(5)(7); // false;

exists

j.exists('a string); // true
j.exists(0); // true
j.exists(null); // false
j.exists(undefined); // false

invert

j.invert(j.isTypeOf('string')('foo')); // false

or

j.or(true, true); // true
j.or(true, false); // true
j.or(false, false); // false

xor

j.xor(true, true); // false
j.xor(true, false); // true
j.xor(false, false); // false

not

j.not(true); // false
j.not(5); // false

Type Predicates

JFP provides several type type predicates, all of which are pre-loaded isTypeOf function returns:

Core

always

var alwaysTrue = j.always(true);

alwaysTrue(); // true
alwaysTrue('over 9000'); // true

apply

j.apply(add, [1, 2]); // 3

argumentsToArray

j.argumentsToArray(arguments); // [object Array]

compose

var isNotNumber = j.compose(j.not, j.isNumber);

isNotNumber(5); // false
isNotNumber('string'); // true

concat

var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
var newArr = j.concat(arr1, arr2); // [1, 2, 3, 4, 5, 6]

arr1 === newArr; // false
arr2 === newArr; // false

conj

var originalArray = [1, 2, 3];
var newArray = j.conj(4, originalArray); // [1, 2, 3, 4];

newArray === originalArray; // false

cons

var originalArray = [1, 2, 3];
var newArray = j.cons(4, originalArray); // [4, 1, 2, 3];

newArray === originalArray; // false

curry

function add  (a, b) {
    return a + b;
}

j.curry(add)(1)(2); // 3
j.curry(add)(1, 2); // 3
j.curry(add, 3)(1)(2)(3); // 3

foldlCompose

var compute = j.foldlCompose(
    j.addBy(1),
    j.multiplyBy(3),
    j.divideBy(2)
);

compute(12); // 19

foldrCompose

var compute = j.foldrCompose(
    j.addBy(1),
    j.multiplyBy(3),
    j.divideBy(2)
);

compute(5); // 9

rcurry

function divide (a, b) {
return a / b;
}

j.rcurry(divide)(1)(2); // 2
j.rcurry(divide)(1, 2); // 0.5
j.rcurry(divide)(2)(1); // 0.5

identity

j.identity('foo'); // foo
j.identity(42); // 42

partial

function add (a, b) {
return a + b;
}

var inc = j.partial(add, 1);

inc(1); // 2
inc(5); // 6

inc(inc(inc(inc(1)))); // 4

pick

j.pick('foo')({ foo: 'bar' }); // bar
j.pick('foo')({ baz: 'bar' }); // j.nil

rcompose

j.compose(j.addBy(1), j.divideBy(3))(8); // 3

recur

var isUndefined = j.isTypeOf('undefined');
var isNil = j.isTypeOf('nil');

var sum = j.recur(function (recur, values, total) {
var result = isUndefined(total) ? 0 : total;
return isNil(values) ? total : recur(j.rest(values), total + j.first(values));
});

repeat

var isEven = j.isTypeOf(function (value) {
    return j.isTypeOf('int')(value) && value % 2 === 0;
});

function threeXPlusOneProblem (value) {
    return isEven(value) ? (value / 2) : (3 * value + 1);
}

j.repeat(threeXPlusOneProblem)(15)(7); // 1
j.repeat(j.concat('foo'))(3)(''); // "foofoofoo"

reverseArgs

function divide (a, b) {
return a / b;
}

j.reverseArgs(divide)(2, 12); // 6

rpartial

function divide (a, b) {
    return a / b;
}

var divBy2 = j.rpartial(divide, 2);

divBy2(1); // 0.5
divBy2(4); // 2

divBy2(divBy2(divBy2(divBy2(12)))); // 0.75

slice

j.slice(1)([1, 2, 3, 4]); // [2, 3, 4]

function foo() {
var args = j.slice(0)(arguments);
// ...
}

cond

j.cond(function(where, then, _default){
    when(j.isTypeOf(number)(a), then(j.multiplyBy(3), a));
    when(_default, then(j.always(a)));
});

Array

all

j.all(j.isTypeOf('string'), ['foo', 'bar', 'baz']); // true
j.all(j.isTypeOf('string'), ['foo', 'bar', 42]); // false

compact

j.compact([1, 2, 0, '', false, null, 3]); // [1, 2, 3]

dropLast

j.dropLast([1, 2, 3, 4]); // [1, 2, 3];

dropNth

j.dropNth(0)([1, 2, 3, 4]); // [2, 3, 4];
j.dropNth(2)([1, 2, 3, 4]); // [1, 2, 4];

filter

var isEven = j.compose(j.equal(0), j.modBy(2));
j.filter(isEven)([1, 2, 3, 4]); // [2, 4]

first

j.first([1, 2, 3, 4]); // 1

find

var divisibleBy3 = j.compose(j.equal(0), j.modBy(3));
j.find(divisibleBy3, [1, 2, 4, 5, 6]); 6
j.find(divisibleBy3, [1, 2, 4, 5, 7]); j.nil

foldl

j.foldl(j.add)([1, 2, 3, 4]); // 10
j.foldl(j.add, 5)([1, 2, 3, 4]); // 15

foldr

j.foldr(j.mod)([2, 5, 8]); // 1
j.foldr(j.mod)([8, 5, 2]); // 2

lastIndexOf

j.lastIndexOf([1, 2, 3, 4]); // 3

map

j.map(j.divideBy(3))([3, 6, 9, 12]); // [1, 2, 3, 4]

none

j.none(j.isTypeOf('number'), ['foo', 'bar', 'baz']); // true
j.none(j.isTypeOf('number'), ['foo', 'bar', 51]); // false

nth

j.nth(2)([1, 2, 3, 4]); // 3;

partition

var isEven = j.compose(j.equal(0), j.modBy(2));

j.partition(isEven)([1, 2, 3, 4]); // [[2, 4], [1, 3]]

pushUnsafe

** Warning: This function will mutate your array **

var myArray = [1, 2, 3, 4];
j.pushUnsafe(myArray)(5); // [1, 2, 3, 4, 5]
console.log(myArray); // [1, 2, 3, 4, 5]

rest

j.rest([1, 2, 3, 4]); // [2, 3, 4]

reverse

j.reverse([1, 2, 3, 4]); // [4, 3, 2, 1]

rfilter

var isEven = j.compose(j.equal(0), j.modBy(2));
j.filter(isEven)([1, [2, [3, 4]]]); // [2, 4]

rmap

j.rmap(j.divideBy(3))([3, 6, [9, 12]]); // [1, 2, 3, 4]

rreduce

j.rreduce(j.add)([1, [2, 3, [4]]]); // 10
j.rreduce(j.add, 5)([1, [2, 3, [4]]]); // 15

some

j.none(j.isTypeOf('number'), ['foo', 'bar', 'baz']); // false
j.none(j.isTypeOf('number'), ['foo', 'bar', 51]); // true

sort

j.sort()([2, 4, 1, 3, 5]); // [1, 2, 3, 4, 5]
j.sort(j.reverseArgs(j.subtract))([2, 4, 1, 3, 5]); // [5, 4, 3, 2, 1]

take

j.take(3)([1, 2, 3, 4, 5]); // [1, 2, 3];

takeUntil

var isEven = j.compose(j.equal(0), j.modBy(2));
j.takeUntil(isEven)([1, 3, 5, 6, 7, 9]); // [1, 3, 5]

until

var isEven = j.compose(j.equal(0), j.modBy(2));

function takeAndDouble(result, value){
    return j.conj(result, value * 2);
}

j.until(isEven)(takeAndDouble, [])([1, 3, 5, 6, 7, 9]); // [2, 6, 10]

Math

add

j.add(1, 2); // 3
j.add(3)(4); // 7

divide

j.divide(6, 3); // 2
j.divide(8)(2); // 4

mod

j.mod(4, 3); // 1
j.mod(7)(5); // 2

multiply

j.multiply(2, 4); // 8
j.multiply(3)(5); // 15

subtract

j.subtract(5, 4); // 1
j.subtract(3)(5); // -2

addBy

j.addBy(5)(6); // 11

divideBy

j.divideBy(3)(12); // 4

modBy

j.modBy(5)(7); // 2

multiplyBy

j.multiplyBy(7)(8); // 56

subtractBy

j.subtractBy(3)(7); // 4

min

j.min(5, 6); // 5
j.min(9)(4); // 4

max

j.max(7, 2); // 7
j.max(8)(5); // 8

inc

j.inc(4); // 5

dec

j.dec(9); // 8

range

j.range(1)(10); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
j.range(1, 3)(10); // [1, 4, 7, 10] 

gt

j.gt(5)(2); // true
j.gt(5)(7); // false

geq

j.geq(5)(2); // true
j.geq(5)(5); // true
j.geq(5)(7); // false

lt

j.gt(5)(2); // false
j.gt(5)(7); // true

leq

j.geq(5)(2); // false
j.geq(5)(5); // true
j.geq(5)(7); // true

between

j.between(1, 5)(4); // true
j.between(1, 5)(5); // true
j.between(1, 5)(10); // false

notBetween

j.notBetween(1, 5)(4); // false
j.notBetween(1, 5)(5); // false
j.notBetween(1, 5)(10); // true

Object

clone

j.clone({foo: 'bar', baz: 'quux'}); {foo: 'bar', baz: 'quux'}

deref

var testObj = {
    foo: {
        bar: {
            baz: [1, 2, 3]
        }
    }
};

j.deref('foo.bar.baz')(testObj); // [1, 2, 3]
j.deref('foo.bar.baz.1')(testObj); // 2
j.deref('foo.bar.baz.4')(testObj); // j.nil

merge

var testObj1 = {
    foo: 'bar',
    baz: 'quux'
};

var testObj2 = {
    baz: 'foo',
    quux: 'bar'
};

j.merge(testObj1, testObj2);

// {
// foo: 'bar',
// baz: 'foo',
// quux: 'bar'
// }

mergeToUnsafe

var myObj = {};

j.mergeToUnsafe(myObj)({foo: 'bar'}); // {foo: 'bar'};
console.log(myObj); // {foo: 'bar'}

shallowClone

toArray

var testObj = {
    foo: 'bar',
    baz: 'quux'
};

j.toArray(testObj); // [['foo', 'bar'], ['baz', 'quux']]

toObject

var testArray = [['foo', 'bar'], ['baz', 'quux']];

j.toObject(testArray); // { foo: 'bar', baz: 'quux' }

toValues

var testObj = {
    foo: 'bar',
    baz: 'quux'
};

j.toValues(testObj); // ['bar', 'quux']