Skip to content

Instantly share code, notes, and snippets.

@elkorn
Created April 19, 2013 05:34
Show Gist options
  • Save elkorn/5418341 to your computer and use it in GitHub Desktop.
Save elkorn/5418341 to your computer and use it in GitHub Desktop.
Functional JS recipes
function toArray(val) {
return Array.prototype.slice.call(val);
}
/**
* Curries a function with given arguments.
*
* @method curry
* @return {Function} The curried version of the given function/
*/
Function.prototype.curry = function() {
if (arguments.length < 1) {
return this; //nothing to curry with - return function
}
var __method = this;
var args = toArray(arguments);
return function() {
return __method.apply(this, args.concat(toArray(arguments)));
};
};
/* Call the function if arguments are passed. */
function maybe(fn) {
return function() {
var i;
if (arguments.length >0) {
for (i = 0; i < arguments.length; ++i) {
if (arguments[i] == null) return;
}
return fn.apply(this, arguments);
}
};
}
/* invoke a function only once. */
function once(fn) {
var done = false;
return function() {
return done ? void 0 : ((done = true), fn.apply(this, arguments))
};
}
var __slice = Array.prototype.slice;
/* left single partial application */
function lpartial (fn, larg) {
return function () {
var args = __slice.call(arguments, 0);
return fn.apply(this, [larg].concat(args));
}
}
/* right single partial application */
function rpartial (fn, rarg) {
return function () {
var args = __slice.call(arguments, 0);
return fn.apply(this, args.concat([rarg]));
}
}
/* Ahhh, the splat. :)
Depends on Array.prototype.map, so have one in there! */
function splat(fn) {
return function(list) {
return Array.prototype.map.call(list, function(something) {
return fn.call(this, something);
});
};
};
/* Encapsulate a value for future use,
while accepting functions to produce side-effects. */
function tap(value, fn) {
if (fn === void 0) {
return curried;
} else {
return curried(fn);
}
function curried(fn) {
if (typeof(fn) === 'function') {
fn(value);
}
return value;
}
}
var __slice = Array.prototype.slice;
/* change function arity or make it variadic */
function variadic (fn) {
var fnLength = fn.length;
if (fnLength < 1) {
return fn;
}
else if (fnLength === 1) {
return function () {
return fn.call(
this,
__slice.call(arguments, 0));
};
}
else {
return function () {
var numberOfArgs = arguments.length,
namedArgs = __slice.call(
arguments,
0,
fnLength - 1),
numberOfMissingNamedArgs = Math.max(
fnLength - numberOfArgs - 1,
0),
argPadding = new Array(numberOfMissingNamedArgs),
variadicArgs = __slice.call(
arguments,
fn.length - 1);
return fn.apply(
this, namedArgs
.concat(argPadding)
.concat([variadicArgs]));
};
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment