curried

curried standard lib

Curried

Awesome curried standard library.

In your project folder:

npm install curried --save

In a file:

var _ = require('curried');

Functions that produce functions - the heart of the library in many senses!

Lifted directly from npm curry; this is the function this library uses to produce its own curried functions.

Chains together functions from right to left, passing the value each function produces into the next:

var appendWithHellYea = function(str){ return str + 'hell yea!' };
var appendSpace = function(str){ return str + ' ' };
var shout = function(str){ return str.toUpperCase() };
var hellYea = _.compose(appendWithHellYea, appendSpace, shout);
 
hellYea('functions!') //= 'FUNCTIONS! hell yea!' 

The above code is the same as appendWithHellYea(appendSpace(shout('functions!')))

To a whole lot of people, compose looks backwards. Pipe is compose the 'right way around', sorta like unix pipes.

var appendWithHellYea = function(str){ return str + 'hell yea!' };
var appendSpace = function(str){ return str + ' ' };
var shout = function(str){ return str.toUpperCase() };
var hellYea = _.pipe(shout, appendSpace, appendWithHellYea);
 
hellYea('functions!') //= 'FUNCTIONS! hell yea!' 

Returns a function that returns false when the original returned true, and vice versa.

var isTruthy = function(a){ return !!};
var isFalsey = _.negate(isTruthy);
 
isFalsey(0) //= true 
isFalsey(1) //= false 
isFalsey('') //= true 
isFalsey('abc') //= false 
isFalsey({}) //= false 

Returns a function with the argument order flipped

var prependWith = _.curry(function(ab){ return a + b });
var appendWith = _.flip(prependWith);
var appendIsm = appendWith('ism');
 
appendIsm('functional') // 'functionalism' 

Returns the value passed into it.

var o = {}
_.identity(o) === o //= true 

In the functional world - where a function is often passed in to do some processing - it's the equivalent of a no-op.

var passCollectionThrough = _.map(_.identity);
 
passCollectionThrough([1, 2, 3]) //= [1, 2, 3] 
 
var pointlesslyComplexIdentity = _.compose(_.identity, _.identity, _.identity);
pointlesslyComplexIdentity('a') //= 'a' 

If you're writing composition-heavy code, sometime's it's really important to be able to inject a step in the middle for debugging purposes.

var log = _.tap(function(value){ console.log(value) });
var shout = _.invoke('toUpperCase');
var appendWith = _.curry(function(ab){ return b + a });
 
_.pipe(shout, log, appendWith('!'))('log this') //= 'LOG THIS!' 
// console.log logs 'LOG THIS' - without the trailing ! 

Creates a function that always returns the same value.

constant('a')() //= 'a' 

This can be particularly useful if you're expected to return a function, but really just want a value. For instance, handling values in promise chains:

getUserFromDB('bob smith')
    .then(null, _.constant('john doe'))
    .then(console.log)

Collection functions work on Arrays AND objects.

var mapInc = _.map(function(a){ return a + 1 });
 
mapInc([1, 2, 3]) //= [2, 3, 4] 
 
mapInc({ x: 1, y: 2, z: 3 }) //= { x: 2, y: 3, z: 4 } 
var isString = function(a){ return typeof a === 'string' };
var filterString = _.filter(isString);
 
filterString([1, 2, 'a', 3, 'b']) //= ['a', 'b'] 
 
filterString({ x: 1, y: 2, z: 'a', a: 3, b: 'b' }) //= { z: 'a', b: 'b' } 
var isString = function(a){ return typeof a === 'string' };
var filterNotString = _.reject(isString);
 
filterNotString([1, 2, 'a', 3, 'b']) //= [1, 2, 3] 
 
filterNotString({ x: 1, y: 2, z: 'a', a: 3, b: 'b' }) //= { x: 1, y: 2, a: 3 } 
var isString = function(a){ return typeof a === 'string' };
var allString = _.every(isString);
 
allString([1, 2, 'a', 3, 'b']) //= false 
allString(['a', '3', 'b']) //= true 
 
allString({ x: 1, y: 2, z: 'a' }) //= false 
allString({ x: '1', y: 'b', z: 'a' }) //= true 
var isString = function(a){ return typeof a === 'string' };
var someString = _.some(isString);
 
someString([1, 2, 'a', 3, 'b']) //= true 
someString([3, 4]) //= false 
 
someString({ x: 1, y: 2, z: 'a' }) //= true 
someString({ x: 1, y: 2, z: 3 }) //= false 
var cat = _.reduce(function(ab){ return a + b });
cat(['a', 'b', 'c']) //= 'abc' 

Since objects don't have guaranteed order in ECMAScript, it's only safe to reduce over objects with operations that don't need arguments in any particular order (commutative).

var sum = _.reduce(function(ab){ return a + b });
sum({ x: 1, y: 2, z: 3 }) //= 6 
var reverseCat = _.reduceRight(function(ab){ return a + b });
reverseCat(['a', 'b', 'c']) //= 'cba' 
 
var sum = _.reduceRight(function(ab){ return a + b });
sum({ x: 1, y: 2, z: 3 }) //= 6 
var catWithPrefix = _.reduceFrom(function(ab){ return a + b }, 'super awesome ');
catWithPrefix(['a', 'b', 'c']) //= 'super awesome abc' 
 
var sumFrom3 = _.reduceFrom(function(ab){ return a + b }, 3);
sumFrom3({ x: 1, y: 2, z: 3 }) //= 9 
var reverseCatWithPrefix = _.reduceRightFrom(function(ab){ return a + b }, 'super awesome ');
reverseCatWithPrefix(['a', 'b', 'c']) //= 'super awesome cba' 
 
var sumFrom3 = _.reduceRightFrom(function(ab){ return a + b }, 3);
sumFrom3({ x: 1, y: 2, z: 3 }) //= 9 

Works on objects - or things that act like an object (i.e. have properties).

var toString = _.invoke('toString');
 
['abc', 1, true, {}].map(toString) //= ['abc', '1', 'true', '[object Object]'] 
var mapInc = _.invokeWith('parse', [function(a){ return a + 1 }]);
mapInc([1, 2, 3]) //= [2, 3, 4] 
var getX = _.get('x');
getX({ x: 2 }) //= 2 
var pick2DCoords = _.pick(['x', 'y']);
var coords3D = { x: 1, y: 2, z: 200 };
 
pick2DCoords(coords3D) //= { x: 1, y: 2 } 
var defaults = _.combine({ firstName: 'joe', lastName: 'bloggs' });
 
defaults({ lastName: 'shufflebottom'} //= { firstName: 'joe', lastName: 'shufflebottom' } 
_.keys({ x: 1, y: 2, z: 3 }) //= ['x', 'y', 'z'] 
_.values({ x: 1, y: 2, z: 3 }) //= [1, 2, 3] 

For those functions that only make sense with an ordered list.

var take5 = _.take(5);
take5([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) //= [1, 2, 3, 4, 5] 
_.head([1, 2, 3]) //= 1 
_.head([]) //= undefined 
_.tail([1, 2, 3]) //= [2, 3] 
_.tail([1]) //= [] 
_.tail([]) //= [] 
_.initial([1, 2, 3]) //= [1, 2] 
_.initial([1]) //= [] 
_.initial([]) //= [] 
_.last([1, 2, 3]) //= 3 
_.last([]) //= undefined