curried

curried standard lib

Usage no npm install needed!

<script type="module">
  import curried from 'https://cdn.skypack.dev/curried';
</script>

README

Curried

Awesome curried standard library.

browser support

Installation

In your project folder:

npm install curried --save

In a file:

var _ = require('curried');

API

FUNCTION

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

curry

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

compose

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!')))

pipe

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!'

negate

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

var isTruthy = function(a){ return !!a };
var isFalsey = _.negate(isTruthy);

isFalsey(0) //= true
isFalsey(1) //= false
isFalsey('') //= true
isFalsey('abc') //= false
isFalsey({}) //= false

flip

Returns a function with the argument order flipped

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

appendIsm('functional') // 'functionalism'

identity

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'

tap

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(a, b){ return b + a });

_.pipe(shout, log, appendWith('!'))('log this') //= 'LOG THIS!'
// console.log logs 'LOG THIS' - without the trailing !

constant

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

Collection functions work on Arrays AND objects.

map

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 }

filter

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' }

reject

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 }

every

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

some

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

reduce

var cat = _.reduce(function(a, b){ 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(a, b){ return a + b });
sum({ x: 1, y: 2, z: 3 }) //= 6

reduceRight

var reverseCat = _.reduceRight(function(a, b){ return a + b });
reverseCat(['a', 'b', 'c']) //= 'cba'

var sum = _.reduceRight(function(a, b){ return a + b });
sum({ x: 1, y: 2, z: 3 }) //= 6

reduceFrom

var catWithPrefix = _.reduceFrom(function(a, b){ return a + b }, 'super awesome ');
catWithPrefix(['a', 'b', 'c']) //= 'super awesome abc'

var sumFrom3 = _.reduceFrom(function(a, b){ return a + b }, 3);
sumFrom3({ x: 1, y: 2, z: 3 }) //= 9

reduceRightFrom

var reverseCatWithPrefix = _.reduceRightFrom(function(a, b){ return a + b }, 'super awesome ');
reverseCatWithPrefix(['a', 'b', 'c']) //= 'super awesome cba'

var sumFrom3 = _.reduceRightFrom(function(a, b){ return a + b }, 3);
sumFrom3({ x: 1, y: 2, z: 3 }) //= 9

OBJECT

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

invoke

var toString = _.invoke('toString');

['abc', 1, true, {}].map(toString) //= ['abc', '1', 'true', '[object Object]']

invokeWith

var mapInc = _.invokeWith('parse', [function(a){ return a + 1 }]);
mapInc([1, 2, 3]) //= [2, 3, 4]

get

var getX = _.get('x');
getX({ x: 2 }) //= 2

pick

var pick2DCoords = _.pick(['x', 'y']);
var coords3D = { x: 1, y: 2, z: 200 };

pick2DCoords(coords3D) //= { x: 1, y: 2 }

combine

var defaults = _.combine({ firstName: 'joe', lastName: 'bloggs' });

defaults({ lastName: 'shufflebottom'} //= { firstName: 'joe', lastName: 'shufflebottom' }

keys

_.keys({ x: 1, y: 2, z: 3 }) //= ['x', 'y', 'z']

values

_.values({ x: 1, y: 2, z: 3 }) //= [1, 2, 3]

ARRAY

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

take

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

head

_.head([1, 2, 3]) //= 1
_.head([]) //= undefined

tail

_.tail([1, 2, 3]) //= [2, 3]
_.tail([1]) //= []
_.tail([]) //= []

initial

_.initial([1, 2, 3]) //= [1, 2]
_.initial([1]) //= []
_.initial([]) //= []

last

_.last([1, 2, 3]) //= 3
_.last([]) //= undefined