(function(root) {
Underscore-contrib (underscore.function.combinators.js 0.0.1) (c) 2013 Michael Fogus, DocumentCloud and Investigative Reporters & Editors Underscore-contrib may be freely distributed under the MIT license.
(function(root) {
Establish the root object, window
in the browser, or global
on the server.
var _ = root._ || require('underscore');
var existy = function(x) { return x != null; };
var truthy = function(x) { return (x !== false) && existy(x); };
var __reverse = [].reverse;
var __slice = [].slice;
_.mixin({
Takes a value and returns a function that always returns said value.
always: function(value) {
return function() { return value; };
},
Takes some value as its first argument and runs it through a pipeline of functions given as the rest arguments.
pipeline: function(/*, funs */){
var funs = arguments;
return function(seed) {
return _.reduce(funs,
function(l,r) { return r(l); },
seed);
};
},
Composes a bunch of predicates into a single predicate that checks all elements of an array for conformance to all of the original predicates.
conjoin: function(/* preds */) {
var preds = arguments;
return function(array) {
return _.every(array, function(e) {
return _.every(preds, function(p) {
return p(e);
});
});
};
},
Composes a bunch of predicates into a single predicate that checks all elements of an array for conformance to any of the original predicates.
disjoin: function(/* preds */) {
var preds = arguments;
return function(array) {
return _.some(array, function(e) {
return _.some(preds, function(p) {
return p(e);
});
});
};
},
Takes a predicate-like and returns a comparator (-1,0,1).
comparator: function(fun) {
return function(x, y) {
if (truthy(fun(x, y)))
return -1;
else if (truthy(fun(y, x)))
return 1;
else
return 0;
};
},
Returns a function that reverses the sense of a given predicate-like.
complement: function(pred) {
return function() {
return !pred.apply(null, arguments);
};
},
Takes a function expecting varargs and returns a function that takes an array and uses its elements as the args to the original function
splat: function(fun) {
return function(array) {
return fun.apply(null, array);
};
},
Takes a function expecting an array and returns a function that takes varargs and wraps all in an array that is passed to the original function.
unsplat: function(fun) {
var funLength = fun.length;
if (funLength < 1) {
return fun;
}
else if (funLength === 1) {
return function () {
return fun.call(this, __slice.call(arguments, 0))
}
}
else {
return function () {
var numberOfArgs = arguments.length,
namedArgs = __slice.call(arguments, 0, funLength - 1),
numberOfMissingNamedArgs = Math.max(funLength - numberOfArgs - 1, 0),
argPadding = new Array(numberOfMissingNamedArgs),
variadicArgs = __slice.call(arguments, fun.length - 1);
return fun.apply(this, namedArgs.concat(argPadding).concat([variadicArgs]))
}
}
},
Returns a function that returns an array of the calls to each given function for some arguments.
juxt: function(/* funs */) {
var funs = arguments;
return function(arg) {
return _.map(funs, function(f) {
return f(arg);
});
};
},
Returns a function that protects a given function from receiving
non-existy values. Each subsequent value provided to fnull
acts
as the default to the original function should a call receive non-existy
values in the defaulted arg slots.
fnull: function(fun /*, defaults */) {
var defaults = _.rest(arguments);
return function(/*args*/) {
var args = _.toArray(arguments);
var sz = _.size(defaults);
for(var i = 0; i < sz; i++) {
if (!existy(args[i]))
args[i] = defaults[i];
}
return fun.apply(null, args);
};
},
Flips the first two args of a function
flip2: function(fun) {
return function(/* args */) {
var tmp = arguments[0];
arguments[0] = arguments[1];
arguments[1] = tmp;
return fun.apply(null, arguments);
};
},
Flips an arbitrary number of args of a function
flip: function(fun) {
return function(/* args */) {
var reversed = __reverse.call(arguments);
return fun.apply(null, reversed);
};
},
k: _.always,
t: _.pipeline
});
})(this);