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 => functionvar 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 => * => booleanj.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 => signetvar signetFactory = require('signet');
var signet = setJfpTypes(signetFactory());
string, function => functionvar add = j.sign('number, number => number', function add (a, b) { return a + b; });
string => stringtypeChain('boundedInt'); // * -> number -> int -> boundedInt
typeChain('array'); // * -> object -> array
()*argumentsarraybooleanbounded<>boundedInt<>boundedString<>comparabledefinedexistsformattedString<>functionindexintmaybenilnotNullnotNilnullnumbernumericobjectobjectKeypairpredicatestringsymboltaggedUnion<>tuple<>typeStringundefinedcomparable => comparable => booleanj.and(true, true); // true
j.and(true, false); // false
comparable => comparable => booleanj.equal(5, 5); // true;
j.equal(5, 7); // false;
j.equal(5)(7); // false;
* => booleanj.exists('a string); // true
j.exists(0); // true
j.exists(null); // false
j.exists(undefined); // false
function => functionj.invert(j.isTypeOf('string')('foo')); // false
comparable => comparable => booleanj.or(true, true); // true
j.or(true, false); // true
j.or(false, false); // false
comparable => comparable => booleanj.xor(true, true); // false
j.xor(true, false); // true
j.xor(false, false); // false
comparable => booleanj.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> => arrayj.argumentsToArray(arguments); // [object Array]
function, function => functionvar 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, ... => functionvar compute = j.foldlCompose(
j.addBy(1),
j.multiplyBy(3),
j.divideBy(2)
);
compute(12); // 19
function, function, ... => functionvar 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 aj.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 => functionj.compose(j.addBy(1), j.divideBy(3))(8); // 3
function => functionvar 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<*> => booleanj.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<*> => indexj.lastIndexOf([1, 2, 3, 4]); // 3
function => array<*> => array<*>j.map(j.divideBy(3))([3, 6, 9, 12]); // [1, 2, 3, 4]
function => array<*> => booleanj.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<*> => booleanj.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 => arrayvar 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 => numberj.add(1, 2); // 3
j.add(3)(4); // 7
number, number => numberj.divide(6, 3); // 2
j.divide(8)(2); // 4
number, number => numberj.mod(4, 3); // 1
j.mod(7)(5); // 2
number, number => numberj.multiply(2, 4); // 8
j.multiply(3)(5); // 15
number, number => numberj.subtract(5, 4); // 1
j.subtract(3)(5); // -2
number => number => numberj.addBy(5)(6); // 11
number => number => numberj.divideBy(3)(12); // 4
number => number => numberj.modBy(5)(7); // 2
number => number => numberj.multiplyBy(7)(8); // 56
number => number => numberj.subtractBy(3)(7); // 4
number => number => numberj.min(5, 6); // 5
j.min(9)(4); // 4
number => number => numberj.max(7, 2); // 7
j.max(8)(5); // 8
int => intj.inc(4); // 5
int => intj.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 => booleanj.gt(5)(2); // true
j.gt(5)(7); // false
number => number => booleanj.geq(5)(2); // true
j.geq(5)(5); // true
j.geq(5)(7); // false
number => number => booleanj.gt(5)(2); // false
j.gt(5)(7); // true
number => number => booleanj.geq(5)(2); // false
j.geq(5)(5); // true
j.geq(5)(7); // true
A < B :: A:number, B:number => number => booleanj.between(1, 5)(4); // true
j.between(1, 5)(5); // true
j.between(1, 5)(10); // false
A < B :: A:number, B:number => number => booleanj.notBetween(1, 5)(4); // false
j.notBetween(1, 5)(5); // false
j.notBetween(1, 5)(10); // true
object => objectj.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 => objectvar testObj1 = {
foo: 'bar',
baz: 'quux'
};
var testObj2 = {
baz: 'foo',
quux: 'bar'
};
j.merge(testObj1, testObj2);
// {
// foo: 'bar',
// baz: 'foo',
// quux: 'bar'
// }
object => object => objectvar myObj = {};
j.mergeToUnsafe(myObj)({foo: 'bar'}); // {foo: 'bar'};
console.log(myObj); // {foo: 'bar'}
object => objectobject => array<tuple<objectKey;*>>var testObj = {
foo: 'bar',
baz: 'quux'
};
j.toArray(testObj); // [['foo', 'bar'], ['baz', 'quux']]
array<tuple<objectKey;*>> => objectvar testArray = [['foo', 'bar'], ['baz', 'quux']];
j.toObject(testArray); // { foo: 'bar', baz: 'quux' }
object => arrayvar testObj = {
foo: 'bar',
baz: 'quux'
};
j.toValues(testObj); // ['bar', 'quux']