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<*>
string, function => function
var add = j.enforce('number, number => number', function add (a, b) { return a + b; });
taggedUnion<typeString;predicate> => * => * => *
j.either('number')(5)(0); // 0
j.either('number')(5)('foo'); // 5
JFP provides several pre-loaded either type functions both for speed and to help keep your code slim and trim
j.either('array')
j.either('boolean')
j.either('function')
j.either('int')
j.either('natural')
j.either('number')
j.either('object')
j.either('string')
j.either('concatable')
j.either('objectInstance')
j.either('referencible')
j.either('defined')
j.either('notNull')
string => * => boolean
j.isTypeOf('string')(5); // false
j.isTypeOf('nil')(j.nil); // true
taggedUnion<typeString;predicate> => * => maybe<defined>
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
JFP provides a pre-loaded maybe defined type function both for speed and to help keep your code slim and trim
j.maybe('defined')
signet => signet
var signetFactory = require('signet');
var signet = setJfpTypes(signetFactory());
string, function => function
var add = j.sign('number, number => number', function add (a, b) { return a + b; });
string => string
typeChain('boundedInt'); // * -> number -> int -> boundedInt
typeChain('array'); // * -> object -> array
()
*
arguments
array
boolean
bounded<>
boundedInt<>
boundedString<>
comparable
defined
exists
formattedString<>
function
index
int
maybe
nil
notNull
notNil
null
number
numeric
object
objectKey
pair
predicate
string
symbol
taggedUnion<>
tuple<>
typeString
undefined
comparable => comparable => boolean
j.and(true, true); // true
j.and(true, false); // false
comparable => comparable => boolean
j.equal(5, 5); // true;
j.equal(5, 7); // false;
j.equal(5)(7); // false;
* => boolean
j.exists('a string); // true
j.exists(0); // true
j.exists(null); // false
j.exists(undefined); // false
function => function
j.invert(j.isTypeOf('string')('foo')); // false
comparable => comparable => boolean
j.or(true, true); // true
j.or(true, false); // true
j.or(false, false); // false
comparable => comparable => boolean
j.xor(true, true); // false
j.xor(true, false); // true
j.xor(false, false); // false
comparable => boolean
j.not(true); // false
j.not(5); // false
JFP provides several type type predicates, all of which are pre-loaded isTypeOf function returns:
j.isTypeOf('array')
j.isTypeOf('boolean')
j.isTypeOf('function')
j.isTypeOf('null')
j.isTypeOf('number')
j.isTypeOf('object')
j.isTypeOf('objectInstance')
j.isTypeOf('string')
j.isTypeOf('undefined')
j.isTypeOf('nil')
j.isTypeOf('pair')
j.isTypeOf('predicate')
j.isTypeOf('int')
j.isTypeOf('natural')
j.isTypeOf('notNull')
j.isTypeOf('notNil')
j.isTypeOf('concatable')
j.isTypeOf('defined')
j.isTypeOf('comparable')
j.isTypeOf('numeric')
j.isTypeOf('referencible')
* => [*] => *
var alwaysTrue = j.always(true);
alwaysTrue(); // true
alwaysTrue('over 9000'); // true
function, array<*> => *
j.apply(add, [1, 2]); // 3
variant<array; arguments> => array
j.argumentsToArray(arguments); // [object Array]
function, function => function
var isNotNumber = j.compose(j.not, j.isNumber);
isNotNumber(5); // false
isNotNumber('string'); // true
array<*>, array<*> => array<*>
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
*, array<*> => array<*>
var originalArray = [1, 2, 3];
var newArray = j.conj(4, originalArray); // [1, 2, 3, 4];
newArray === originalArray; // false
*, array<*> => array<*>
var originalArray = [1, 2, 3];
var newArray = j.cons(4, originalArray); // [4, 1, 2, 3];
newArray === originalArray; // false
function, [int], [array<*>] => [*] => *
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
function, function, ... => function
var compute = j.foldlCompose(
j.addBy(1),
j.multiplyBy(3),
j.divideBy(2)
);
compute(12); // 19
function, function, ... => function
var compute = j.foldrCompose(
j.addBy(1),
j.multiplyBy(3),
j.divideBy(2)
);
compute(5); // 9
function, [int], [array<*>] => [*] => *
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
Signature: * => *
a
and returns value a
j.identity('foo'); // foo
j.identity(42); // 42
function, [*] => [*] => *
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
string => object => maybe<defined>
j.pick('foo')({ foo: 'bar' }); // bar
j.pick('foo')({ baz: 'bar' }); // j.nil
function, function => function
j.compose(j.addBy(1), j.divideBy(3))(8); // 3
function => function
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));
});
function => number => * => *
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"
function => [*] => *
function divide (a, b) {
return a / b;
}
j.reverseArgs(divide)(2, 12); // 6
function, [*] => [*] => *
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
int, [int] => taggedUnion<array<*>;arguments> => array<*>
j.slice(1)([1, 2, 3, 4]); // [2, 3, 4]
function foo() {
var args = j.slice(0)(arguments);
// ...
}
function<function;function;boolean> => *
j.cond(function(where, then, _default){
when(j.isTypeOf(number)(a), then(j.multiplyBy(3), a));
when(_default, then(j.always(a)));
});
function => array<*> => boolean
j.all(j.isTypeOf('string'), ['foo', 'bar', 'baz']); // true
j.all(j.isTypeOf('string'), ['foo', 'bar', 42]); // false
[array] => array<*>
j.compact([1, 2, 0, '', false, null, 3]); // [1, 2, 3]
array<*> => array<*>
j.dropLast([1, 2, 3, 4]); // [1, 2, 3];
index => array<*> => array<*>
j.dropNth(0)([1, 2, 3, 4]); // [2, 3, 4];
j.dropNth(2)([1, 2, 3, 4]); // [1, 2, 4];
function => array<*> => array<*>
var isEven = j.compose(j.equal(0), j.modBy(2));
j.filter(isEven)([1, 2, 3, 4]); // [2, 4]
array<*> => maybe<defined>
j.first([1, 2, 3, 4]); // 1
function<*> => array<*> => maybe<defined>
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
function, [*] => array<*> => *
j.foldl(j.add)([1, 2, 3, 4]); // 10
j.foldl(j.add, 5)([1, 2, 3, 4]); // 15
function, [*] => array<*> => *
j.foldr(j.mod)([2, 5, 8]); // 1
j.foldr(j.mod)([8, 5, 2]); // 2
array<*> => index
j.lastIndexOf([1, 2, 3, 4]); // 3
function => array<*> => array<*>
j.map(j.divideBy(3))([3, 6, 9, 12]); // [1, 2, 3, 4]
function => array<*> => boolean
j.none(j.isTypeOf('number'), ['foo', 'bar', 'baz']); // true
j.none(j.isTypeOf('number'), ['foo', 'bar', 51]); // false
index => array<*> => maybe<defined>
j.nth(2)([1, 2, 3, 4]); // 3;
predicate => array => tuple<array;array>
var isEven = j.compose(j.equal(0), j.modBy(2));
j.partition(isEven)([1, 2, 3, 4]); // [[2, 4], [1, 3]]
array => * => array
** 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]
taggedUnion<array<*>;arguments> => array<*>
j.rest([1, 2, 3, 4]); // [2, 3, 4]
array<*> => array<*>
j.reverse([1, 2, 3, 4]); // [4, 3, 2, 1]
function => array<*> => array<*>
var isEven = j.compose(j.equal(0), j.modBy(2));
j.filter(isEven)([1, [2, [3, 4]]]); // [2, 4]
function => array<*> => array<*>
j.rmap(j.divideBy(3))([3, 6, [9, 12]]); // [1, 2, 3, 4]
function, [*] => array<*> => *
j.rreduce(j.add)([1, [2, 3, [4]]]); // 10
j.rreduce(j.add, 5)([1, [2, 3, [4]]]); // 15
function => array<*> => boolean
j.none(j.isTypeOf('number'), ['foo', 'bar', 'baz']); // false
j.none(j.isTypeOf('number'), ['foo', 'bar', 51]); // true
[*] => array<*> => array<*>
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]
[index] => function<array<*>>
j.take(3)([1, 2, 3, 4, 5]); // [1, 2, 3];
predicate => array => array
var isEven = j.compose(j.equal(0), j.modBy(2));
j.takeUntil(isEven)([1, 3, 5, 6, 7, 9]); // [1, 3, 5]
predicate => function, * => array => *
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]
number, number => number
j.add(1, 2); // 3
j.add(3)(4); // 7
number, number => number
j.divide(6, 3); // 2
j.divide(8)(2); // 4
number, number => number
j.mod(4, 3); // 1
j.mod(7)(5); // 2
number, number => number
j.multiply(2, 4); // 8
j.multiply(3)(5); // 15
number, number => number
j.subtract(5, 4); // 1
j.subtract(3)(5); // -2
number => number => number
j.addBy(5)(6); // 11
number => number => number
j.divideBy(3)(12); // 4
number => number => number
j.modBy(5)(7); // 2
number => number => number
j.multiplyBy(7)(8); // 56
number => number => number
j.subtractBy(3)(7); // 4
number => number => number
j.min(5, 6); // 5
j.min(9)(4); // 4
number => number => number
j.max(7, 2); // 7
j.max(8)(5); // 8
int => int
j.inc(4); // 5
int => int
j.dec(9); // 8
int, [int] => int => array<int>
j.range(1)(10); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
j.range(1, 3)(10); // [1, 4, 7, 10]
number => number => boolean
j.gt(5)(2); // true
j.gt(5)(7); // false
number => number => boolean
j.geq(5)(2); // true
j.geq(5)(5); // true
j.geq(5)(7); // false
number => number => boolean
j.gt(5)(2); // false
j.gt(5)(7); // true
number => number => boolean
j.geq(5)(2); // false
j.geq(5)(5); // true
j.geq(5)(7); // true
A < B :: A:number, B:number => number => boolean
j.between(1, 5)(4); // true
j.between(1, 5)(5); // true
j.between(1, 5)(10); // false
A < B :: A:number, B:number => number => boolean
j.notBetween(1, 5)(4); // false
j.notBetween(1, 5)(5); // false
j.notBetween(1, 5)(10); // true
object => object
j.clone({foo: 'bar', baz: 'quux'}); {foo: 'bar', baz: 'quux'}
string => object => maybe<defined>
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
object, object => object
var testObj1 = {
foo: 'bar',
baz: 'quux'
};
var testObj2 = {
baz: 'foo',
quux: 'bar'
};
j.merge(testObj1, testObj2);
// {
// foo: 'bar',
// baz: 'foo',
// quux: 'bar'
// }
object => object => object
var myObj = {};
j.mergeToUnsafe(myObj)({foo: 'bar'}); // {foo: 'bar'};
console.log(myObj); // {foo: 'bar'}
object => object
object => array<tuple<objectKey;*>>
var testObj = {
foo: 'bar',
baz: 'quux'
};
j.toArray(testObj); // [['foo', 'bar'], ['baz', 'quux']]
array<tuple<objectKey;*>> => object
var testArray = [['foo', 'bar'], ['baz', 'quux']];
j.toObject(testArray); // { foo: 'bar', baz: 'quux' }
object => array
var testObj = {
foo: 'bar',
baz: 'quux'
};
j.toValues(testObj); // ['bar', 'quux']