CARVIEW |
Underscore-contrib (0.3.0)
The brass buckles on Underscore's utility belt - a contributors' library for Underscore.
Introduction
Places
Why underscore-contrib?
While Underscore provides a bevy of useful tools to support functional programming in JavaScript, it can't (and shouldn't) be everything to everyone. Underscore-contrib is intended as a home for functions that, for various reasons, don't belong in Underscore proper. In particular, it aims to be:
- a home for functions that are limited in scope, but solve certain point problems, and
- a proving ground for features that belong in Underscore proper, but need some advocacy and/or evolution (or devolution) to get them there.
Use
In the Browser
First, you'll need Underscore version 1.6.0 or higher. Then you can grab the relevant underscore-contrib sub-libraries and simply add something like the following to your pages:
<script type="text/javascript" src="underscore.js"></script>
<script type="text/javascript" src="underscore.object.builders.js"></script>
At the moment there are no cross-contrib dependencies (i.e. each sub-library can stand by itself), but that may change in the future.
In Node.js
Using contrib in Node is very simple. Just install it with npm:
npm install underscore-contrib --save
Then require it within your project like so:
var _ = require('underscore-contrib');
The _
variable will be a copy of Underscore with contrib's methods already
mixed in.
License
_.contrib is open sourced under the MIT license.
Sub-libraries
The _.contrib library currently contains a number of related capabilities, aggregated into the following files.
- underscore.array.builders - functions to build arrays
- underscore.array.selectors - functions to take things from arrays
- underscore.collections.walk - functions to walk and transform nested JavaScript objects
- underscore.function.arity - functions to manipulate and fix function argument arity
- underscore.function.combinators - functions to combine functions to make new functions
- underscore.function.iterators - functions to lazily produce, manipulate and consume sequence iterators
- underscore.function.predicates - functions that return
true
orfalse
based on some criteria - underscore.object.builders - functions to build JavaScript objects
- underscore.object.selectors - functions to pick things from JavaScript objects
- underscore.util.existential - functions that check for the existence or truthiness of JavaScript data types
- underscore.util.operators - functions that wrap common (or missing) JavaScript operators
- underscore.util.strings - functions to work with strings
- underscore.util.trampolines - functions to facilitate calling functions recursively without blowing the stack
The links above are to the annotated source code. Full-blown _.contrib documentation is in the works. Contributors welcomed.
array.builders
Functions to build arrays. View Annotated Source
cat
Signature: _.cat(... arrays:Array ...)
The _.cat
function provides a way to concatenate zero or more heterogeneous arrays into one.
_.cat(); // 0-args
//=> []
_.cat([]); // 1-arg, empty array
//=> []
_.cat([1,2,3]); // 1-arg
//=> [1,2,3]
_.cat([1,2,3],[4,5,6]); // 2-args
//=> [1,2,3,4,5,6]
_.cat([1,2,3],[4,5,6],[7]); // 3+ args
//=> [1,2,3,4,5,6,7]
Not every argument to _.cat
needs to be an array; other types are accepted.
Signature: _.cat(... elems:Any ...)
_.cat(1,[2],3,4); // mixed args
//=> [1,2,3,4]
The _.cat
function will also work with the arguments
object as if it were an array.
Signature: _.cat(... elems:Arguments ...)
function f(){ return _.cat(arguments, 4,5,6); }
f(1,2,3);
//=> [1,2,3,4,5,6]
chunk
The _.chunk
function, by default, accepts an array and a number and splits and returns a new array representing the original array split into some number of arrays of the given size:
_.chunk([0,1,2,3], 2);
//=> , [[0,1],[2,3]]
If the original array cannot completely fulfill the chunk scheme then the array returned will drop the undersized final chunk:
_.chunk([0,1,2,3,4], 2);
//=> , [[0,1],[2,3]]
You can pass an optional third argument to _.chunk
to pad out the final array chunk should it fall short. If the value given as the third argument is not an array then it is repeated the needed number of times:
_.chunk([0,1,2,3,4], 3, '_');
//=> , [[0,1,2],[3,'_','_']]
If you given an array as the optional third argument then that array is used to pad in-place as needed:
_.chunk([0,1,2,3,4], 3, ['a', 'b']);
//=> , [[0,1,2],[3,'a','b']]
chunkAll
The _.chunkAll
function is similar to _.chunk
except for the following. First, _.chunkAll
will never drop short chunks from the end:
_.chunkAll([0,1,2,3,4], 3);
//=> , [[0,1,2],[3]]
Also, _.chunkAll
takes an optional third argument signifying that paritions should be built from skipped regions:
_.chunkAll(_.range(10), 2, 4);
//=> [[0,1],[4,5],[8,9]]
cons
Signature: _.cons(head:Any, tail:Array)
The _.cons
function provides a way to "construct" a new array by taking some element and putting it at the front of another array.
_.cons(0, []);
//=> [0]
_.cons(1, [2]);
//=> [1,2]
_.cons([0], [1,2,3]);
//=> [0,1,2,3]
The _.cons
function also can be used to create pairs if the second argument is not an array.
Signature: _.cons(head:Any, tail:Any)
_.cons(1, 2);
//=> [1,2]
_.cons([1], 2);
//=> [[1],2]
Finally, _.cons
will operate with the arguments
object.
Signature: _.cons(head:Any, tail:Arguments)
function f() { return _.cons(0, arguments) }
f(1,2,3);
//=> [0,1,2,3]
cycle
The _.cycle
function takes an integer value used to build an array of that size containing the number of iterations through the given array, strung end-to-end as many times as needed. An example is probably more instructive:
_.cycle(5, [1,2,3]);
//=> [1,2,3,1,2]
interpose
The _.interpose
function takes an array and an element and returns a new array with the given element inserted betwixt every element in the original array:
_.interpose([1,2,3], 0);
//=> [1,0,2,0,3]
If there are no betweens (i.e. empty and single-element arrays), then the original array is returned:
_.interpose([1], 0);
//=> [1]
_.interpose([], 0);
//=> []
iterateUntil
The _.iterateUntil
function takes a function used as a result generator, a function used as a stop-check and a seed value and returns an array of each generated result. The operation of _.iterateUntil
is such that the result generator is passed the seed to start and each subsequent result which will continue until a result fails the check function (i.e. returns falsey). An example is best:
var dec = function(n) { return n - 1; };
var isPos = function(n) { return n > 0; };
The dec
result generator takes a number and decrements it by one. The isPos
predicate takes a number and returns true
if it's positive. Using these two functions you can build an array of every number from 6
to 0
, inclusive:
_.iterateUntil(dec, isPos, 6);
//=> [5,4,3,2,1]
That is, the array only contains every number from 5
down to 1
because when the result of dec
got to 0
the isPos
check failed (i.e. went falsey) thus terminating the execution.
keepIndexed
The _.keepIndexed
function takes an array and a function and returns a new array filled with the non-null return results of the given function on the elements or keys in the given array:
_.keepIndexed([1,2,3], function(k) {
return i === 1 || i === 2;
});
//=> [false, true, true]
If you return either null
or undefined
then the result is dropped from the resulting array:
_.keepIndexed(['a','b','c'], function(k, v) {
if (k === 1) return v;
});
//=> ['b']
mapcat
There are times when a mapping operation produces results contained in arrays, but the final result should be flattened one level. For these circumstances you can use _.mapcat
to produce results:
var array = [1,2,null,4,undefined,6];
var errors = _.mapcat(array, function(e,i) {
if (e == null) {
return ["Element @" + i + " is bad"];
}
else {
return [];
}
});
Inspecting the contents of errors
shows:
["Element @2 is bad", "Element @4 is bad"]
The _.mapcat
function is equivalent to _.cat.apply(array, _.map(array,fun))
.
reductions
The _.reductions
function is similar to Underscore's builtin _.reduce
function except that it returns an array of every intermediate value in the folding operation:
_.reductions([1,2,3,4,5], function(agg, n) {
return agg + n;
}, 0);
//=> [1,3,6,10,15]
The last element in the array returned from _.reductions
is the answer that you would get if you had just chosen to use _.reduce
.
repeat
Signature: _.repeat(t:Integer, value:Any)
The _.repeat
function takes an integer value used to build an array of that size containing the value given:
_.repeat(5, 'a');
//=> ['a','a','a','a','a']
splitAt
The _.splitAt
function takes an array and a numeric index and returns a new array with two embedded arrays representing a split of the original array at the index provided:
_.splitAt([1,2,3,4,5], 2);
//=> [[1,2],[3,4,5]]
_.splitAt([1,2,3,4,5], 0);
//=> [[],[1,2,3,4,5]]
The operation of _.splitAt
is safe if the index provided is outside the range of legal indices:
_.splitAt([1,2,3,4,5], 20000);
//=> [[1,2,3,4,5],[]]
_.splitAt([1,2,3,4,5], -1000);
//=> [[],[1,2,3,4,5]]
_.splitAt([], 0);
//=> [[],[]]
takeSkipping
The _.takeSkipping
function takes an array and a number and returns a new array containing every nth element in the original array:
_.takeSkipping(_.range(10), 2);
//=> [0,2,4,6,8]
The _.takeSkipping
function is safe against numbers larger or smaller than the array size:
_.takeSkipping(_.range(10), 100000);
//=> [0]
_.takeSkipping(_.range(10), -100);
//=> []
weave
The _.weave
function works similarly to _.interpose
(shown above) except that it accepts an array used as the interposition values. In other words, _.weave
takes two arrays and returns a new array with the original elements woven together. An example would help:
_.weave(['a','b','c'], [1,2,3]);
//=> ['a',1,'b',2,'c',3]
The array returned from _.weave
will be as long as the longest array given with the woven entries stopping according to the shortest array:
_.weave(['a','b','c'], [1]);
//=> ['a',1,'b','c']
The _.interleave
function is an alias for _.weave
.
array.selectors
Functions to take things from arrays. View Annotated Source
best
Signature: _.best(array:Array, fun:Function)
Returns the "best" value in an array based on the result of a given function.
_.best([1, 2, 3, 4, 5], function(x, y) {
return x > y;
});
//=> 5
dropWhile
Signature: _.dropWhile(array:Array, pred:Function)
Drops elements for which the given function returns a truthy value.
_.dropWhile([-2,-1,0,1,2], isNeg);
//=> [0,1,2]
keep
Signature: _.keep(array:Array, fun:Function)
Returns an array of existy results of a function over a source array.
_.keep([1, 2, 3, 4, 5], function(val) {
if (val % 3 === 0) {
return val;
}
});
// => [3]
nth
Signature: _.nth(array:Array, index:Number[, guard:Any])
The _.nth
function is a convenience for the equivalent array[n]
. The
optional guard
value allows _.nth
to work correctly as a callback for
_.map
.
_.nth(['a','b','c'], 2);
//=> 'c'
If given an index out of bounds then _.nth
will return undefined
:
_.nth(['a','b','c'], 2000);
//=> undefined
The _.nth
function can also be used in conjunction with _.map
and _.compact
like so:
var b = [['a'],['b'],[]];
_.compact(_.map(b, function(e) { return _.nth(e,0) }));
//=> ['a','b']
If wrapping a function around _.nth
is too tedious or you'd like to partially apply the index then Underscore-contrib offers any of _.flip2
, _.fix
or _.curryRight2
to solve this.
partitionBy
Signature: _.partitionBy(array:Array, fun:Function)
Takes an array and partitions it into sub-arrays as the given predicate changes truth sense.
_.partitionBy([1,2,2,3,1,1,5], _.isEven);
// => [[1],[2,2],[3,1,1,5]]
_.partitionBy([1,2,2,3,1,1,5], _.identity);
// => [[1],[2,2],[3],[1,1],[5]]
second
Signature: _.second(array:Array, index:Number[, guard:Any])
The _.second
function is a convenience for the equivalent array[1]
. The
optional guard
value allows _.second
to work correctly as a callback for
_.map
.
_.second(['a','b']);
//=> 'b'
_.map([['a','b'], _.range(10,20)], _.second);
//=> ['b',11]
You can also pass an optional number to the _.second
function to take a number of elements from an array starting with the second element and ending at the given index:
_.second(_.range(10), 5)
//=> [1, 2, 3, 4]
takeWhile
Signature: _.takeWhile(array:Array, pred:Function)
The _.takeWhile
function takes an array and a function and returns a new array containing the first n elements in the original array for which the given function returns a truthy value:
var isNeg = function(n) { return n < 0; };
_.takeWhile([-2,-1,0,1,2], isNeg);
//=> [-2,-1]
third
Signature: _.third(array:Array, index:Number[, guard:Any])
The _.third
function is a convenience for the equivalent array[2]
. The
optional guard
value allows _.third
to work correctly as a callback for
_.map
.
_.third(['a','b','c']);
//=> 'c'
_.map([['a','b','c'], _.range(10,20)], _.third);
//=> ['c',12]
You can also pass an optional number to the _.third
function to take a number of elements from an array starting with the third element and ending at the given index:
_.third(_.range(10), 5)
//=> [2, 3, 4]
collections.walk
Functions to recursively walk collections which are trees.
Documentation should use Journo formats and standards.
_.walk = walk;
postorder: function(obj, visitor, context)
preorder: function(obj, visitor, context)
walk(obj, visitor, null, context)
map: function(obj, strategy, visitor, context)
pluck: function(obj, propertyName)
pluckRec: function(obj, propertyName)
_.walk.collect = _.walk.map;
function.arity
Functions which manipulate the way functions work with their arguments.
arity
Signature: _.arity(numberOfArgs:Number, fun:Function)
Returns a new function which is equivalent to fun
, except that the new
function's length
property is equal to numberOfArgs
. This does not limit
the function to using that number of arguments. It's only effect is on the
reported length.
function addAll() {
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
sum = sum + arguments[i];
}
return sum;
}
addAll.length
// => 0
var addAllWithFixedLength = _.arity(2, addAll);
addAllWithFixedLength.length
// => 2
addAllWithFixedLength(1, 1, 1, 1);
// => 4
binary
Signature: _.binary(fun:Function)
Returns a new function which accepts only two arguments and passes these
arguments to fun
. Additional arguments are discarded.
function addAll() {
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
sum = sum + arguments[i];
}
return sum;
}
var add2 = _.binary(addAll);
add2(1, 1);
// => 2
add2(1, 1, 1, 1);
// => 2
curry
Signature: _.curry(func:Function[, reverse:Boolean])
Returns a curried version of func
. If reverse
is true, arguments will be
processed from right to left.
function add3 (x, y, z) {
return x + y + z;
}
var curried = _.curry(add3);
// => function
curried(1);
// => function
curried(1)(2);
// => function
curried(1)(2)(3);
// => 6
curry2
Signature: _.curry2(fun:Function)
Returns a curried version of func
, but will curry exactly two arguments, no
more or less.
function add2 (a, b) {
return a + b;
}
var curried = _.curry2(add2);
// => function
curried(1);
// => function
curried(1)(2);
// => 3
curry3
Signature: _.curry3(fun:Function)
Returns a curried version of func
, but will curry exactly three arguments, no
more or less.
function add3 (a, b, c) {
return a + b + c;
}
var curried = _.curry3(add3);
// => function
curried(1);
// => function
curried(1)(2);
// => function
curried(1)(2)(3);
// => 6
curryRight
Signature: _.curryRight(func:Function)
Aliases: _.rCurry
Returns a curried version of func
where arguments are processed from right
to left.
function divide (a, b) {
return a / b;
}
var curried = _.curryRight(divide);
// => function
curried(1);
// => function
curried(1)(2);
// => 2
curried(2)(1);
// => 0.5
curryRight2
Signature: _.curryRight2(func:Function)
Aliases: _.rcurry2
Returns a curried version of func
where a maxium of two arguments are
processed from right to left.
function concat () {
var str = "";
for (var i = 0; i < arguments.length; i++) {
str = str + arguments[i];
}
return str;
}
var curried = _.curryRight2(concat);
// => function
curried("a");
// => function
curried("a")("b");
// => "ba"
curryRight3
Signature: _.curryRight3(func:Function)
Aliases: _.rcurry3
Returns a curried version of func
where a maxium of three arguments are
processed from right to left.
function concat () {
var str = "";
for (var i = 0; i < arguments.length; i++) {
str = str + arguments[i];
}
return str;
}
var curried = _.curryRight3(concat);
// => function
curried("a");
// => function
curried("a")("b");
// => function
curried("a")("b")("c");
// => "cba"
fix
Signature: _.fix(fun:Function[, value:Any...])
Fixes the arguments to a function based on the parameter template defined by
the presence of values and the _
placeholder.
function add3 (a, b, c) {
return a + b + c;
}
var fixedFirstAndLast = _.fix(add3, 1, _, 3);
// => function
fixedFirstAndLast(2);
// => 6
fixedFirstAndLast(10);
// => 14
quaternary
Signature: _.quaternary(fun:Function)
Returns a new function which accepts only four arguments and passes these
arguments to fun
. Additional arguments are discarded.
function addAll() {
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
sum = sum + arguments[i];
}
return sum;
}
var add4 = _.quaternary(addAll);
add4(1, 1, 1, 1);
// => 4
add4(1, 1, 1, 1, 1, 1);
// => 4
ternary
Signature: _.ternary(fun:Function)
Returns a new function which accepts only three arguments and passes these
arguments to fun
. Additional arguments are discarded.
function addAll() {
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
sum = sum + arguments[i];
}
return sum;
}
var add3 = _.ternary(addAll);
add3(1, 1, 1);
// => 3
add3(1, 1, 1, 1, 1, 1);
// => 3
unary
Signature: _.unary(fun:Function)
Returns a new function which accepts only one argument and passes this
argument to fun
. Additional arguments are discarded.
function logArgs() {
console.log(arguments);
}
var logOneArg = _.unary(logArgs);
logOneArg("first");
// => ["first"]
logOneArg("first", "second");
// => ["first"]
function.combinators
Functions that are combinators.
always
Signature: _.always(value:Any)
Aliases: _.k
Takes value
and returns a function that will always return value
.
var platonicForm = _.always("Eternal & Unchangeable");
platonicForm();
// => "Eternal & Unchangeable"
bound
Signature: _.bound(obj:Object, fname:String)
Returns function property of an object by name, bound to object.
var aristotle = {
name: "Aristotle",
telos: "flourishing",
stateTelos: function() {
return this.name + "'s telos is " + this.telos;
}
};
var stateAristotlesTelos = _.bound(aristotle, "stateTelos");
stateAristotlesTelos();
// => "Aristotle's Telos is flourishing"
comparator
Signature: _.comparator(fun:Function)
Takes a binary predicate-like function and returns a comparator function (return
values of -1
, 0
, 1
) which can be used as a callback for _.sort
or
Array.prototype.sort
.
var lessOrEqual = function(x, y) { return x <= y; };
var arr = [0, 1, -2];
arr.sort(_.comparator(lessOrEqual));
// => [-2, 0, 1]
complement
Signature: _.complement(pred:Function)
Returns a function that reverses the sense of a given predicate-like.
function isAugustine (val) {
return val === "Augustine";
}
isNotAugustine = _.complement(isAugustine);
isNotAugustine("Dionysius");
// => True
conjoin
Signature: _.conjoin(pred:Function...)
Composes multiple predicates into a single predicate that checks all elements of an array for conformance to all of the original predicates.
function startsWithA (val) {
return val[0] === "A";
}
function endsWithE (val) {
return val[val.length - 1] === "e";
}
var names = ["Aristotle", "Aquinas", "Plato", "Augustine"];
var startsAAndEndsE = _.conjoin(startsWithA, endsWithE);
startsAAndEndsE(names);
// => ["Aristotle", "Augustine"]
disjoin
Signature: _.disjoin(pred:Function...)
Composes multiple predicates into a single predicate that checks all elements of an array for conformance to any of the original predicates.
function startsWithA (val) {
return val[0] === "A";
}
function endsWithE (val) {
return val[val.length - 1] === "e";
}
var names = ["Aristotle", "Aquinas", "Plato", "Augustine"];
var startsAOrEndsE = _.disjoin(startsWithA, endsWithE);
startsAOrEndsE(names);
// => ["Aristotle", "Aquinas", "Augustine"]
juxt
Signature: _.juxt(fun:Function...)
Returns a function whose return value is an array of the results of calling each of the original functions with the arguments.
function firstChar (val) {
return val[0];
}
function lastChar (val) {
return val[val.length - 1];
}
var firstAndLastChars = _.juxt(firstChar, lastChar);
firstAndLastChars("Etruria");
// => ["E", "a"]
flip
Signature: _.flip(fun:Function)
Returns a function that works identically to fun
, but accepts the arguments
in reverse order.
function regionCapitol (region, capitol) {
return "The capitol of " + region + " is " + capitol;
}
capitolRegion = _.flip(regionCapitol);
capitolRegion("Thessalonica", "Illyrica");
// => "The capitol of Illyrica is Thessalonica"
flip2
Signature: _.flip2(fun:Function)
Returns a function that works identically to fun
, but accepts the first two
arguments in reverse order. The order of all other arguments remains the same.
function regionCapitol (region, capitol) {
return "The capitol of " + region + " is " + capitol;
}
capitolRegion = _.flip2(regionCapitol);
capitolRegion("Thessalonica", "Illyrica");
// => "The capitol of Illyrica is Thessalonica"
fnull
Signature: _.fnull(fun:Function[, default:Any...])
Returns a function that protects fun
from receiving non-existy values. Each
subsequent value provided to fnull
acts as the default to the original
fun
should a call receive non-existy values in the defaulted arg slots.
function getLength (val) {
return val.length;
}
safeGetLength = _.fnull(getLength, []);
safeGetLength([1, 2, 3]);
// => 3
safeGetLength(null);
// => 0
functionalize
Signature: _.functionalize(fun:Function[, default:Any...])
Takes a method-style function (one which uses this
) and pushes this
into the
argument list. The returned function uses its first argument as the
receiver/context of the original function, and the rest of the arguments are
used as the original's entire argument list.
var militaryUnits = {
centuria: "80 men",
cohort: "480 men",
getDescription: function (unitName) {
return this[unitName];
}
};
var getDescription = _.functionalize(militaryUnits.getDescription);
var rulers = {
Leonidas: "King of Sparta",
Augustus: "First Roman Emperor"
};
getDescription(rulers, "Augustus");
// => "First Roman Emperor"
mapArgs
Signature: _.mapArgs(fun:Function)
Takes a target function and returns a new function which accepts a mapping function, which in turn returns a function that will map its arguments before calling the original target function.
function doubleNum (x) { return 2 * x; }
function squareNum (x) { return x * x; }
var squareThenDouble = _.mapArgs(doubleNum)(squareNum);
squareThenDouble(3);
// => 18
mapArgsWith
Signature: _.mapArgs(mapFun:Function)
Takes a mapping function and returns a new combinator function which will take a target function and return a new version which maps its arguments with the mapping function before executing the body of the target function.
function doubleNum (x) { return 2 * x; }
function squareNum (x) { return x * x; }
var squareArgs = _.mapArgsWith(squareNum);
var squareThenDouble = squareArgs(doubleNum);
squareThenDouble(3);
// => 18
methodize
Signature: _.methodize(func:Function)
Takes a function and pulls the first argument out of the argument list and into
this
position. The returned function calls the original with its receiver
(this
) prepending the argument list. The original is called with a receiver
of null
.
function describe (obj) {
return obj.name + ": " + obj.description;
}
var democritus = {
name: "Democritus",
description: "originator of the atomic hypothesis",
describe: _.methodize(describe)
};
democritus.describe();
// => "Democritus: originator of the atomic hypothesis"
pipeline
Signature: _.pipeline(func:Function[, func2:Function...])
or _.pipeline(funcArr:Array)
Aliases: _.t
Takes a list of functions, either as an array or as individual arguments and returns a function that takes some value as its first argument and runs it through a pipeline of the original functions given.
function halveNum (x) { return x / 2; };
function squareNum (x) { return x * x; };
function doubleNum (x) { return 2 * x; };
var halveSquareDouble = _.pipeline(halveNum, squareNum, doubleNum);
halveSquareDouble(1);
// => 0.5
var doubleSquareHalve = _.pipeline([doubleNum, squareNum, halveNum]);
doubleSquareHalve(1);
// => 2
splat
Signature: _.splat(fun:Function)
Takes a function expecting one or more arguments and returns a function that takes an array and uses its elements as the arguments to the original function. This roughly corresponds to the spread operator in ECMAScript 6.
function listTwoNames (a, b) {
return a.name + " & " + b.name;
}
var listTwoNamesFromArray = _.splat(listTwoNames);
listTwoNamesFromArray([{ name: "Zeno" }, { name: "Parmenides"}]);
// => "Zeno & Parmenides"
unsplat
Signature: _.unsplat(fun:Function)
Aliases: _.unsplatr
Takes a function expecting an array as its last argument and returns a function which works identically, but takes a list of trailing arguments instead. Roughly corresponds to rest parameters in ECMAScript 6.
function joinWith (joiner, arr) {
return arr.join(joiner);
}
var joinArgsWith = _.unsplat(joinWith);
joinArgsWith(" & ", "Plutarch", "Proclus");
// => "Plutarch & Proclus"
unsplatl
Signature: _.unsplatl(fun:Function)
Similar to unsplat, but takes a function expecting an array as its first argument and returns a function which works identically, but takes a list of leading arguments instead. Roughly corresponds to rest parameters in ECMAScript 6.
function joinWith (arr, joiner) {
return arr.join(joiner);
}
var joinArgsWith = _.unsplat(joinWith);
joinArgsWith("Olympiodorus", "Syrianus", " & ");
// => "Olympiodorus & Syrianus"
function.iterators
Functions to iterate over collections.
iterators.accumulate
Signature: _.iterators.accumulate(iter:Function, binaryFn:Function, initial:Any)
Returns a function that when called will iterate one step with iter
and return
the value currently accumulated by using binaryFn
. The function will return undefined
once all values have been iterated over.
var generalsIterator = _.iterators.List(["Hannibal", "Scipio"]);
function countLetters(memo, element) {
return memo + element.length;
}
var generalsAcc = _.iterators.accumulate(generalsIterator, countLetters, 0);
generalsAcc();
// => 8
generalsAcc();
// => 14
generalsAcc();
// => undefined
iterators.accumulateWithReturn
Signature: _.iterators.accumulateWithReturn(iter:Function, binaryFn:Function, initial:Any)
Acts similarly to accumulate, except that binaryFn
is expected to return an
array of two elements. The value of the first element is given to the next run
of binaryFn
. The value of the second element is yielded by the iterator.
var fiveIter = _.iterators.List([1, 2, 3, 4, 5]);
function adderWithMessage (state, element) {
return [state + element, 'Total is ' + (state + element)];
}
var i = _.iterators.accumulateWithReturn(fiveIter, adderWithMessage, 0);
i();
// => "Total is 1"
i();
// => "Total is 3"
i();
// => "Total is 6"
iterators.drop
Signature: _.iterators.drop(iter:Function[, numberToDrop:Number])
Given an iterator function iter
, will return a new iterator which iterates
over the same values as iter
, except that the first numberToDrop
values
will be omitted. If numberToDrop
is not provided, it will default to 1
.
var deityIter = _.iterators.List(["Zeus", "Apollo", "Athena", "Aphrodite"]);
var goddessIter = _.iterators.drop(deityIter, 2);
goddessIter();
// => "Athena"
goddessIter();
// => "Aphrodite"
iterators.foldl
Signature: _.iterators.foldl(iter:Function, binaryFn:Function[, seed:Any])
Aliases: iterators.reduce
Boils down the values given by iter
into a single value. The seed
is the
initial state. The binaryFn
is given two arguments: the seed
and the
current value yielded by iter
.
var sybylIter = _.iterators.List(["cumaean", "tiburtine"]);
function commaString (a, b) { return a + ", " + b; }
_.iterators.foldl(sybylIter, commaString);
// => "cumaean, tiburtine"
iterators.K
Signature: _.iterators.K(value:Any)
Aliases: iterators.constant
Returns a function that when invoked will always return value
.
var ceasar = _.iterators.K("Ceasar");
ceasar();
// => "ceasar"
iterators.List
Signature: _.iterators.List(array:Array)
Returns an iterator that when invoked will iterate over the contents of array
.
var triumvirIter = _.iterators.List(["Ceasar", "Pompey", "Crassus"]);
triumvirIter();
// => "Ceasar"
triumvirIter();
// => "Pompey"
triumvirIter();
// => "Crassus"
iterators.map
Signature: _.iterators.map(iter:Function, unaryFn:Function)
Returns a new iterator function which on each iteration will return the result
of running iter
's current value through unaryFn
.
var notablesIter = _.iterators.List(["Socrates", "Plato"]);
function postfixAthenian (val) {
return val + ", Athenian";
}
var notableAtheniansIter = _.iterators.map(notablesIter, postfixAthenian);
notableAtheniansIter();
// => "Socrates, Athenian"
notableAtheniansIter();
// => "Plato, Athenian"
iterators.mapcat
Signature: _.iterators.mapcat(iter:Function, unaryFn:Function)
Returns an iterator which is the result of flattening the contents of iter
,
and mapping the results with unaryFn
.
function naturalSmallerThan (x) {
return _.iterators.List(_.range(0, x));
}
var treeIter = _.iterators.Tree([1, [2]]);
var smallerThanIter = _.iterators.mapcat(treeIter, naturalSmallerThan);
smallerThanIter();
// => 0
smallerThanIter();
// => 0
smallerThanIter();
// => 1
iterators.numbers
Signature: _.iterators.numbers([start:Number])
Returns an iterator of integers which will begin with start
and increment by
one for each invocation. If start
is not provided it will default to 1
.
var twoAndUp = _.iterators.numbers(2);
twoAndUp();
// => 2
twoAndUp();
// => 3
twoAndUp();
// => 4
iterators.range
Signature: _.iterators.range([from:Number, to:Number, by:Number])
Returns an iterator whose values consist of numbers beginning with from
, ending with to
, in steps of size by
.
var by5 = _.iterators.range(5, Infinity, 5);
by5();
// => 5
by5();
// => 10
by5();
// => 15
iterators.reject
Signature: _.iterators.reject(iter:Function, unaryPredicatFn:Function)
Returns an iterator consisting of the values of iter
which are not flagged
true
by unaryPredicateFn
.
var philosophers = ["Anaximander", "Socrates", "Heraclitus"];
var philosophersIter = _.iterators.List(philosophers);
function isSocrates (val) {
return val === "Socrates";
}
var preSocraticsIter = _.iterators.reject(philosophersIter, isSocrates);
preSocraticsIter()
// => "Anaximander"
preSocraticsIter()
// => "Heraclitus"
iterators.select
Signature: _.iterators.select(iter:Function, unaryPredicatFn:Function)
Aliases: iterators.find
, iteraters.filter
Returns an iterator consisting of the values of iter
which are flagged
true
by unaryPredicateFn
.
var philosophers = ["Anaximander", "Socrates", "Heraclitus"];
var philosophersIter = _.iterators.List(philosophers);
function isSocrates (val) {
return val === "Socrates";
}
var socraticIter = _.iterators.select(philosophersIter, isSocrates);
socraticIter()
// => "Socrates"
iterators.slice
Signature: _.iterators.slice(iter:Function, numberToDrop:Number, numberToTake:Number)
Returns an iterator whose values consist of iter
's after removing
numberToDrop
from the head, and a maxiumum of numberToTake
of the remaining.
If numberToTake
is not specified, all of iter
's remaining values will be
used.
var emperors = ["Augustus", "Tiberius", "Caligula", "Claudius"];
var emperorsIter = _.iterators.List(emperors);
var middleEmperorsIter = _.iterators.slice(emperorsIter, 1, 2);
middleEmperorsIter();
// => "Tiberius"
middleEmperorsIter();
// => "Caligula"
middleEmperorsIter();
// => undefined
iterators.take
Signature: _.iterators.take(iter:Function[, numberToTake:Number])
Returns an iterator consisting of the first numberToTake
values yielded by
iter
. If numberToTake
is not provided, it will default to 1
.
var byzantineEmperors = ["Constantine", "Constantius", "Constans"];
var byzantineEmperorsIter = _.iterators.List(byzantineEmperors);
var firstTwoEmperorsIter = _.iterators.take(byzantineEmperorsIter, 2);
firstTwoEmperorsIter();
// => "Constantine"
firstTwoEmperorsIter();
// => "Constantius"
firstTwoEmperorsIter();
// => undefined
iterators.Tree
Signature: _.iterators.Tree(array:Array);
Returns an iterator that yields the individual values of a tree array
.
var rulers = ["Augustus", ["Constantine"], ["Leo", ["Charlemagne"]]];
var rulersIter = _.iterators.Tree(rulers);
rulersIter();
// => "Augustus"
rulersIter();
// => "Constantine"
rulersIter();
// => "Leo"
rulersIter();
// => "Charlemagne"
iterators.unfold
Signature: _.iterators.unfold(seed:Any, unaryFn:Function)
function greatify (val) {
return val + " the Great";
}
var greatIter = _.iterators.unfold("Constantine", greatify);
greatIter();
// => "Constantine the Great"
greatIter();
// => "Constantine the Great the Great"
greatIter();
// => "Constantine the Great the Great the Great"
iterators.unfoldWithReturn
Signature: _.iterators.unfold(seed:Any, unaryFn:Function)
Acts similarly to unfold, except that unaryFn
is expected to return an array
with two elements. The value of the first element is given to the next run of
unaryFn
. The value of the second element is yielded by the iterator.
var i = _.iterators.unfoldWithReturn(1, function(n) {
return [n + 1, n * n];
});
i();
// => 1
i();
// => 4
i();
// => 9
function.predicates
Functions which return whether the input meets a condition.
isAssociative
Signature: isAssociative(value:Any)
Returns a boolean indicating whether or not the value is an associative object.
An associative object is one where its elements can be accessed via a key or
index (e.g. arrays, arguments
, objects).
_.isAssociative(["Athens", "Sparta"]);
// => true
_.isAssociative(42);
// => false
isDecreasing
Signature: _.isDecreasing(values:Any...)
Checks whether the arguments are monotonically decreasing values (i.e. whether each argument is less than the previous argument.)
_.isDecreasing(3, 2, 1);
// => true
_.isDecreasing(15, 12, 2);
// => true
_.isDecreasing(2, 3);
// => false
isEven
Signature: _.isEven(value:Any)
Checks whether the value is an even number.
_.isEven(12);
// => true
_.isEven(3);
// => false
_.isEven({});
// => false
isFloat
Signature: _.isFloat(value:Any)
Checks whether the value is a "float." For the purposes of this function, a float
is a numeric value that is not an integer. A numeric value may be a number, a
string containing a number, a Number
object, etc.
NOTE: JavaScript itself makes no distinction between integers and floats. For
the purposes of this function both 1
and 1.0
are considered integers.
_.isFloat(1.1);
// => true
_.isFloat(1);
// => false
_.isFloat(1.0);
// => false
_.isFloat("2.15");
// => true
isIncreasing
Signature: _.isIncreasing(value:Any...)
Checks whether the arguments are monotonically increasing values (i.e. each argument is greater than the previous argument.)
_.isIncreasing(1, 12, 15);
// => true
_.isIncreasing(1);
// => true
_.isIncreasing(5, 4);
// => false
isIndexed
Signature: _.isIndexed(value:Any)
Checks whether the value is "indexed." An indexed value is one which accepts a numerical index to access its elements. (e.g. arrays and strings)
NOTE: Underscore does not support cross-browser consistent use of strings as array-like values, so be wary in IE 8 when using string objects and in IE7 and earlier when using string literals & objects.
_.isIndexed("Socrates");
// => true
_.isIndexed({poison: "hemlock"});
// => false
isInstanceOf
Signature: _.isInstanceOf(value:Any, constructor:Function)
Checks whether the value is an instance of the constructor.
_.isInstanceOf(new Date(), Date);
// => true
_.isInstanceOf("Hippocrates", RegExp);
// => false
isInteger
Signature: _.isInteger(value:Any)
Checks whether the value is a numeric integer. A numeric value can be a string
containing a number, a Number
object, etc.
_.isInteger(18);
// => true
_.isInteger("18");
// => true
_.isInteger(2.5);
// => false
_.isInteger(-1);
// => true
isJSON
Signature: _.isJSON(value:Any)
Checks whether the value is valid JSON. See the spec for more information on what constitutes valid JSON.
NOTE: This function relies on JSON.parse
which is not available in IE7 and
earlier.
_.isJSON('{ "name": "Crockford" }');
// => true
_.isJSON({ name: "Crocket" });
// => false
isNegative
Signature: _.isNegative(value:Any)
Checks whether the value is a negative number.
_.isNegative(-2);
// => true
_.isNegative(5);
// => false
isNumeric
Signature: _.isNumeric(value:Any)
A numeric is something that contains a numeric value, regardless of its type. It
can be a string containing a numeric value, exponential notation, a Number
object, etc.
_.isNumeric("14");
// => true
_.isNumeric("fourteen");
// => false
isOdd
Signature: _.isOdd(value:Any)
Checks whether the value is an odd number.
_.isOdd(3);
// => true
_.isOdd(2);
// => false
_.isOdd({});
// => false
isPlainObject
Signature: _.isPlainObject(value:Any);
Checks whether the value is a "plain" object created as an object literal ({}
)
or explicitly constructed with new Object()
. Instances of other constructors
are not plain objects.
_.isPlainObject({});
// => true
_.isPlainObject(new Date());
// => false
_.isPlainObject([]);
// => false
isPositive
Signature: _.isPositive(value:Any)
Checks whether the value is a positive number.
_.isPositive(21);
// => true
_.isPositive(-3);
// => false
isSequential
Signature: _.isSequential(value:Any)
Checks whether the value is a sequential composite type (i.e. arrays and
arguments
).
_.isSequential(["Herodotus", "Thucidydes");
// => true
_.isSequential(new Date);
// => false
isValidDate
Signature: _.isValidDate(value:Any)
Checks whether the value is a valid date. That is, the value is both an instance
of Date
and it represents an actual date.
Warning: This function does not verify
whether the original input to Date
is a real date. For instance,
new Date("02/30/2014")
is considered a valid date because Date
coerces that
into a representation of 03/02/2014. To validate strings representing a date,
consider using a date/time library like Moment.js.
_.isValidDate(new Date("January 1, 1900"));
// => true
_.isValidDate(new Date("The Last Great Time War"));
// => false
isZero
Signature: _.isZero(value:Any)
Checks whether the value is 0
.
_.isZero(0);
// => true
_.isZero("Pythagoras");
// => false
object.builders
Functions to build objects.
frequencies
Signature: _.frequencies(arr:Array)
Returns an object whose property keys are the values of arr
's elements. The
property values are a count of how many times that value appeared in arr
.
var citations = ["Plato", "Aristotle", "Plotinus", "Plato"];
_.frequencies(citations);
// => { Plato: 2, Aristotle: 1, Plotinus: 1 }
merge
Signature: _.merge(obj1:Object[, obj:Object...])
Returns a new object resulting from merging the passed objects. Objects are processed in order, so each will override properties of the same name occurring in earlier arguments.
Returns null
if called without arguments.
var a = {a: "alpha"};
var b = {b: "beta"};
var threeGreekLetters = _.merge(a, b, {g: "gamma"});
a;
// => {a: "alpha"}
b;
// => {b: "beta"}
threeGreekLetters;
// => { a: "alpha", b: "beta", g: "gamma" }
renameKeys
Signature: _.renameKeys(obj:Object, keyMap:Object)
Takes an object (obj
) and a map of keys (keyMap
) and returns a new object
where the keys of obj
have been renamed as specified in keyMap
.
_.renameKeys({ a: 1, b: 2 }, { a: "alpha", b: "beta" });
// => { alpha: 1, beta: 2 }
setPath
Signature: _.setPath(obj:Object, value:Any, ks:Array, defaultValue:Any)
Sets the value of a property at any depth in obj
based on the path described
by the ks
array. If any of the properties in the ks
path don't exist, they
will be created with defaultValue
.
Note that the original object will not be mutated. Instead, obj
will
be cloned deeply.
var obj = {};
var plotinusObj = _.setPath(obj, "Plotinus", ["Platonism", "Neoplatonism"], {});
obj;
// => {}
plotinusObj;
// => { Platonism: { Neoplatonism: "Plotinus" } }
obj === plotinusObj;
// => false;
snapshot
Signature: _.snapshot(obj:Object)
Snapshots/clones an object deeply.
var schools = { plato: "Academy", aristotle: "Lyceum" };
_.snapshot(schools);
// => { plato: "Academy", aristotle: "Lyceum" }
schools === _.snapshot(schools);
// => false
updatePath
Signature: _.updatePath(obj:Object, fun:Function, ks:Array, defaultValue:Any)
Updates the value at any depth in a nested object based on the path described by
the ks
array. The function fun
is called with the current value and is
expected to return a replacement value. If no keys are provided, then the
object itself is presented to fun
. If a property in the path is missing, then
it will be created with defaultValue
.
Note that the original object will not be mutated. Instead, obj
will
be cloned deeply.
var imperialize = function (val) {
if (val == "Republic") return "Empire";
else return val;
};
_.updatePath({ rome: "Republic" }, imperialize, ["rome"]);
// => { rome: "Empire" }
var obj = { earth: { rome: "Republic" } };
var imperialObj = _.updatePath(obj, imperialize, ["earth", "rome"]);
imperialObj;
// => { earth: { rome: "Empire" }}
obj;
// => { earth: { rome: "Republic" }}
obj === imperialObj;
// => false
object.selectors
Functions to select values from an object.
accessor
Signature: _.accessor(field:String)
Returns a function that will attempt to look up a named field in any object that it is given.
var getName = _.accessor('name');
getName({ name: 'Seneca' });
// => 'Seneca'
dictionary
Signature: _.dictionary(obj:Object)
Given an object, returns a function that will attempt to look up a field that it is given.
var generals = {
rome: "Scipio",
carthage: "Hannibal"
};
var getGeneralOf = _.dictionary(generals);
getGeneralOf("rome");
// => "Scipio"
getPath
Signature: _.getPath(obj:Object, ks:String|Array)
Gets the value at any depth in a nested object based on the path described by
the keys given. Keys may be given as an array of key names or as a single string
using JavaScript property access notation.
Returns undefined
if the path cannot be reached.
var countries = {
greece: {
athens: {
playwright: "Sophocles"
},
notableFigures: ["Alexander", "Hippocrates", "Thales"]
}
}
};
_.getPath(countries, "greece.athens.playwright");
// => "Sophocles"
_.getPath(countries, "greece.sparta.playwright");
// => undefined
_.getPath(countries, ["greece", "athens", "playwright"]);
// => "Sophocles"
_.getPath(countries, ["greece", "sparta", "playwright"]);
// => undefined
_.getPath(countries, ["greece", "notableFigures", 1]);
// => "Hippocrates"
_.getPath(countries, "greece.notableFigures[2]");
// => "Thales"
_.getPath(countries, "greece['notableFigures'][2]")
// => "Thales"
hasPath
Signature: _.hasPath(obj:Object, ks:String|Array)
Returns a boolean indicating whether there is a property at the path described by the keys given. Keys may be given as an array of key names or as a single string using JavaScript property access notation.
var countries = {
greece: {
athens: {
playwright: "Sophocles"
},
notableFigures: ["Alexander", "Hippocrates", "Thales"]
}
}
};
_.hasPath(countries, "greece.athens.playwright");
// => true
_.hasPath(countries, "greece.sparta.playwright");
// => false
_.hasPath(countries, ["greece", "athens", "playwright"]);
// => true
_.hasPath(countries, ["greece", "sparta", "playwright"]);
// => false
_.hasPath(countries, ["greece", "notableFigures", 1]);
// => true
_.hasPath(countries, "greece.notableFigures[2]");
// => true
_.hasPath(countries, "greece['notableFigures'][2]");
// => true
_.hasPath(countries, "greece.sparta[2]");
// => false
keysFromPath
Signature: _.keysFromPath(path:String)
Takes a string in JavaScript object path notation and returns an array of keys.
_.keysFromPath("rome.emperors[0]['first-name']");
// => ["rome", "emperors", "0", "first-name"]
kv
Signature: _.kv(obj:Object, key:String)
Returns the key/value pair for a given property in an object, undefined if not found.
var playAuthor = {
"Medea": "Aeschylus"
};
_.kv(playAuthor, "Medea");
// => ["Medea", "Aeschylus"]
_.kv(playAuthor, "Hamlet");
// => undefined
omitWhen
Signature: _.omitWhen(obj, pred:Function)
Returns a copy of obj
omitting any properties that the predicate (pred
)
function returns true
for. The predicat function is invoked with each
property value, like so: pred(propValue)
.
var playwrights = {
euripedes: "Greece",
shakespere: "England"
};
_.omitWhen(playwrights, function (country) { return country == "England" });
// => { euripedes: "Greece" }
pickWhen
Signature: _.pickWhen(obj:Object, pred:Function)
Returns a copy of obj
containing only properties that the predicate (pred
)
function returns true
for. The predicate function is invoked with each
property value, like so: pred(propValue)
.
var playwrights = {
euripedes: "Greece",
shakespere: "England"
};
_.pickWhen(playwrights, function (country) { return country == "England" });
// => { shakespeare: "England" }
selectKeys
Signature: `_.selectKeys(obj:Object, ks:Array);
Returns a copy of obj
containing only the properties listed in the ks
array.
var philosopherCities = {
Philo: "Alexandria",
Plato: "Athens",
Plotinus: "Rome"
}
_.selectKeys(philosopherCities, ["Plato", "Plotinus"]);
// => { Plato: "Athens", Plotinus: "Rome" }
omitPath
Signature: `_.omitPath(obj:Object, ks:String|Array);
Returns a copy of obj
excluding the value represented by the ks
path.
Path may be given as an array or as a dot-separated string.
If the path contains an array, the value of the path will be removed from all the array elements.
var test = {
foo: true,
bar: false,
baz: 42,
dada: {
carlos: {
pepe: 9
},
pedro: 'pedro'
}
};
_.omitPath(test, 'dada.carlos.pepe');
// => {foo: true, bar: false, baz: 42, dada: {carlos: {}, pedro: 'pedro'}}
util.existential
Functions which deal with whether a value "exists."
exists
Signature: _.exists(value:Any)
Checks whether or not the value is "existy." Both null
and undefined
are
considered non-existy values. All other values are existy.
_.exists(null);
// => false
_.exists(undefined);
// => false
_.exists({});
// = > true
_.exists("Sparta");
// => true
falsey
Signature: _.falsey(value:Any)
Checks whether the value is falsey. A falsey value is one which coerces to
false
in a boolean context.
_.falsey(0);
// => true
_.falsey("");
// => true
_.falsey({});
// => false
_.falsey("Corinth");
// => false
firstExisting
Signature: _.firstExisting(value:Any[, value:Any...])
Returns the first existy argument from the argument list.
_.firstExisting("Socrates", "Plato");
// => "Socrates"
_.firstExisting(null, undefined, "Heraclitus");
// => "Heraclitus"
not
Signature: _.not(value:Any)
Returns a boolean which is the opposite of the truthiness of the original value.
_.not(0);
// => true
_.not(1);
// => false
_.not(true);
// => false
_.not(false);
// => true
_.not({});
// => false
_.not(null);
// => true
truthy
Signature: _.truthy(value:Any)
Checks whether the value is truthy. A truthy value is one which coerces to
true
in a boolean context.
_.truthy({});
// => true
_.truthy("Athens");
// => true
_.truthy(0);
// => false
_.truthy("");
// => false
util.operators
Functions which wrap JavaScript's operators.
add
Signature: _.add(value:Number, value:Number[, value:Number...])
, _.add(values:Array)
Returns the sum of the arguments.
_.add(1, 2, 3, 4);
// => 10
_.add([1, 2, 3, 4]);
// => 10
bitwiseAnd
Signature: _.bitwiseAnd(value:Any, value:Any[, value:Any...])
, _.bitwiseAnd(values:Array)
Returns the result of using the &
operator on the arguments.
_.bitwiseAnd(1, 3);
// => 1
_.bitwiseAnd(1, 3, 2);
// => 0
_.bitwiseAnd([1, 3, 2]);
// => 0
bitwiseLeft
Signature: _.bitwiseLeft(value:Any, value:Any[, value:Any...])
, _.bitwiseLeft(values:Array)
Returns the result of using the <<
operator on the arguments.
_.bitwiseLeft(1, 3);
// => 8
_.bitwiseLeft(1, 3, 2);
// => 32
_.bitwiseLeft([1, 3, 2]);
// => 32
bitwiseRight
Signature: _.bitwiseRight(value:Any, value:Any[, value:Any...])
, _.bitwiseRight(values:Array)
Returns the result of using the >>
operator on the arguments.
_.bitwiseRight(3, 1);
// => 1
_.bitwiseRight(3, 1, 3);
// => 0
_.bitwiseRight([3, 1, 3]);
// => 0
bitwiseNot
Signature: _.bitwiseNot(value:Any)
Returns the result of using the ~
operator on the value.
_.bitwiseNot(1);
// => -2
_.bitwiseNot(2);
// => -3
bitwiseOr
Signature: _.bitwiseOr(value:Any, value:Any[, value:Any...])
, _.bitwiseOr(values:Array)
Returns the result of using the |
operator on the arguments.
_.bitwiseOr(1, 3);
// => 3
_.bitwiseOr(1, 3, 4);
// => 7
_.bitwiseOr([1, 3, 4]);
// => 7
bitwiseXor
Signature: _.bitwiseXor(value:Any, value:Any[, value:Any...])
,_.bitwiseXor(values:Array)
Returns the result of using the ^
operator on the arguments.
_.bitwiseXor(1, 3);
// => 2
_.bitwiseXor(1, 3, 3);
// => 1
_.bitwiseXor([1, 3, 3]);
// => 1
bitwiseZ
Signature: _.bitwiseZ(value:Any, value:Any[, value:Any...])
, _.bitwiseZ(values:Array)
Returns the result of using the >>>
operator on the arguments.
_.bitwiseZ(72, 32);
// => 72
_.bitwiseZ(72, 32, 2);
// => 18
_.bitwiseZ([72, 32, 2]);
// => 18
dec
Signature: _.dec(value:Number)
Returns the result of decrementing the value by 1
.
_.dec(2);
// => 1
div
Signature: _.div(value:Number, value:Number[, value:Number...])
, _.div(values:Array)
Returns the quotient of the arguments.
_.div(8, 2);
// => 4
_.div(8, 2, 2);
// => 2
_.div([8, 2, 2]);
// => 2
eq
Signature: _.eq(value:Any, value:Any[, value:Any...])
,_.eq(values:Array)
Compares the arguments with loose equality (==
).
_.eq(1, "1");
// => true
_.eq(1, 15);
// => false
_.eq(1, true, "1");
// => true
_.eq(1, 1, 15);
// => false
_.eq([1, 1, 15]);
// => false
gt
Signature: _.gt(value:Any, value:Any[, value:Any...])
, _.gt(values:Array)
Checks whether each argument is greater than the previous argument.
_.gt(1, 2);
// => true
_.gt(1, 2, 3);
// => true
_.gt(1, 6, 2);
// => false
_.gt([1, 6, 2]);
// => false
gte
Signature: _.gte(value:Any, value:Any[, value:Any...])
, _.gte(values:Array)
Checks whether each argument is greater than or equal to the previous argument.
_.gte(1, 2);
// => true
_.gte(1, 1, 3);
// => true
_.gte(1, 6, 2);
// => false
_.gte([1, 6, 2]);
// => false
inc
Signature: _.inc(value:Number)
Returns the result of incrementing the value by 1
.
_.inc(2);
// => 3
lt
Signature: _.lt(value:Any, value:Any[, value:Any...])
, _.lt(values:Array)
Checks whether each argument is less than the previous argument.
_.lt(2, 1);
// => true
_.lt(2, 1, 0);
// => true
_.lt(2, 1, 12);
// => false
_.lt([2, 1, 12]);
// => false
lte
Signature: _.lte(value:Any, value:Any[, value:Any...])
, _.lte(values:Array)
Checks whether each argument is less than or equal to the previous argument.
_.lte(2, 1);
// => true
_.lte(2, 1, 1);
// => true
_.lte(2, 1, 12);
// => false
_.lte([2, 1, 12]);
// => false
mul
Signature: _.mul(value:Number, value:Number[, value:Number...])
, _.mul(values:Array)
Returns the product of the arguments.
_.mul(1, 2, 3, 4);
// => 24
_.mul([1, 2, 3, 4]);
// => 24
mod
Signature: _.mod(dividend:Number, divisor:Number)
Returns the remainder of dividing dividend
by divisor
.
_.mod(26, 5);
// => 1
_.mod(14, 3);
// => 2
neg
Signature: _.neg(num:Number)
Returns a new number with the opposite sign value of num
.
_.neg(5);
// => -5
_.neg(-3);
// => 3
neq
Signature: _.neq(value:Any, value:Any[, value:Any...])
, _.neq(values:Array)
Checks whether each argument is not equal to the previous argument, using loose
inequality (!=
).
_.neq(2, 1);
// => true
_.neq(2, 1, 1);
// => true
_.neq(1, 1);
// => false
_.neq([1, 1]);
// => false
not
Signature: _.not(value:Any)
Returns a boolean which is the opposite of the truthiness of the original value.
_.not(0);
// => true
_.not(1);
// => false
_.not(true);
// => false
_.not(false);
// => true
_.not({});
// => false
_.not(null);
// => true
seq
Signature: _.seq(value:Any, value:Any[, value:Any...])
, _.seq(values:Array)
Checks whether the arguments are strictly equal (===
) to each other.
_.seq(2, 2);
// => true
_.seq(2, "2");
// => false
_.seq(2, 2, 2);
// => true
_.seq([2, 2, 2]);
// => true
sneq
Signature: _.sneq(value:Any, value:Any[, value:Any...])
, _.sneq(values:Array)
Checks whether the arguments are strictly not equal (!==
) to each other.
_.sneq(2, 2);
// => false
_.sneq(2, "2");
// => true
_.sneq(2, 2, 2);
// => false
_.sneq([2, 2, 2]);
// => false
sub
Signature: _.sub(value:Number, value:Number[, value:Number...])
, _.sub(values:Array)
Returns the difference of the arguments.
_.sub(10, 3);
// => 7
_.sub(10, 3, 5);
// => 2
_.sub([10, 3, 5]);
// => 2
util.strings
Functions for working with strings.
camelCase
Signature: _.camelCase(string:String)
Converts a dash-separated string to camel case. Opposite of toDash.
_.camelCase("ancient-greece");
// => "ancientGreece"
explode
Signature: _.explode(s:String)
Explodes a string into an array of characters. Opposite of implode.
_.explode("Plato");
// => ["P", "l", "a", "t", "o"]
fromQuery
Signature: _.fromQuery(str:String)
Takes a URL query string and converts it into an equivalent JavaScript object. Opposite of toQuery
_.fromQuery("forms%5Bperfect%5D=circle&forms%5Bimperfect%5D=square");
// => { forms: { perfect: "circle", imperfect: "square" } }
implode
Signature: _.implode(a:Array)
Implodes an array of strings into a single string. Opposite of explode.
_.implode(["H", "o", "m", "e", "r"]);
// => "Homer"
strContains
Signature: _.strContains(str:String, search:String)
Reports whether a string contains a search string.
_.strContains("Acropolis", "polis");
// => true
toDash
Signature: _.toDash(string:String)
Converts a camel case string to a dashed string. Opposite of camelCase.
_.toDash("thisIsSparta");
// => "this-is-sparta"
toQuery
Signature: _.toQuery(obj:Object)
Takes an object and converts it into an equivalent URL query string. Opposite of fromQuery.
_.toQuery({ forms: { perfect: "circle", imperfect: "square" } });
// => "forms%5Bperfect%5D=circle&forms%5Bimperfect%5D=square"
util.trampolines
Trampoline functions.
done
Signature: _.done(value:Any)
A utility for wrapping a function's return values so they can be used by
_.trampoline
. See below.
trampoline
Signature: _.trampoline(fun:Function[, args:Any...])
Provides a way of creating recursive functions that won't exceed a JavaScript
engine's maximum recursion depth. Rather than writing a naive recursive
function, the function's base cases must return _.done(someValue)
, and
recursive calls must be wrapped in a returned function.
In order to create a trampolined function that can be used in the same way as
a naive recursive function, use _.partial
as illustrated below.
function isEvenNaive (num) {
if (num === 0) return true;
if (num === 1) return false;
return isEvenNaive(Math.abs(num) - 2);
}
isEvenNaive(99999);
// => InternalError: too much recursion
function isEvenInner (num) {
if (num === 0) return _.done(true);
if (num === 1) return _.done(false);
return function () { return isEvenInner(Math.abs(num) - 2); };
}
_.trampoline(isEvenInner, 99999);
// => false
var isEven = _.partial(_.trampoline, isEvenInner);
isEven(99999);
// => false
Changelog
0.3.0
- Contrib now requires Underscore 1.6.0 or higher.
- Rename
partition
andpartitionAll
tochunk
andchunkAll
to avoid name conflicts with Underscore'spartition
- #115 - Added
toQuery
andfromQuery
- #134 - Switch
always
to an alias of Underscore'sconstant
. - #132 - The combinators sub-library now supports method combinators - #14