|
// Code copied from http://eliperelman.com/fn.js/ |
|
|
|
var fn = {}; |
|
|
|
fn.toArray = function (collection) { |
|
return [].slice.call(collection); |
|
}; |
|
|
|
fn.cloneArray = fn.toArray; |
|
|
|
fn.apply = function (handler, args) { |
|
return handler.apply(null, args); |
|
}; |
|
|
|
fn.concat = function () { |
|
var args = fn.toArray(arguments); |
|
var first = args[ 0 ]; |
|
|
|
if (!fn.is('array', first) && !fn.is('string', first)) { |
|
first = args.length ? [ first ] : [ ]; |
|
} |
|
|
|
return first.concat.apply(first, args.slice(1)); |
|
}; |
|
|
|
fn.type = function (value) { |
|
// If the value is null or undefined, return the stringified name, |
|
// otherwise get the [[Class]] and compare to the relevant part of the value |
|
return value == null ? |
|
'' + value : |
|
{ }.toString.call(value).slice(8, -1).toLowerCase(); |
|
}; |
|
|
|
fn.is = function (type, value) { |
|
return type === fn.type(value); |
|
}; |
|
|
|
fn.partial = function () { |
|
var args = fn.toArray(arguments); |
|
var handler = args[0]; |
|
var partialArgs = args.slice(1); |
|
|
|
return function () { |
|
return fn.apply(handler, fn.concat(partialArgs, fn.toArray(arguments)) ); |
|
}; |
|
}; |
|
|
|
fn.identity = function (arg) { |
|
return arg; |
|
}; |
|
|
|
fn.reverse = function (collection) { |
|
return fn.cloneArray(collection).reverse(); |
|
}; |
|
|
|
var currier = function makeCurry(rightward) { |
|
return function (handler, arity) { |
|
if (handler.curried) { |
|
return handler; |
|
} |
|
|
|
arity = arity || handler.length; |
|
|
|
var curry = function curry() { |
|
var args = fn.toArray(arguments); |
|
|
|
if (args.length >= arity) { |
|
var transform = rightward ? 'reverse' : 'identity'; |
|
return fn.apply(handler, fn[ transform ](args)); |
|
} |
|
|
|
var inner = function () { |
|
return fn.apply(curry, args.concat(fn.toArray(arguments))); |
|
}; |
|
|
|
inner.curried = true; |
|
|
|
return inner; |
|
}; |
|
|
|
curry.curried = true; |
|
|
|
return curry; |
|
}; |
|
}; |
|
|
|
fn.curry = currier(false); |
|
|
|
fn.curryRight = currier(true); |
|
|
|
// Partial Application |
|
|
|
var fullName = function (firstName, lastName) { |
|
return firstName + ' ' + lastName; |
|
}; |
|
|
|
var billName = fn.partial(fullName, 'Bill'); |
|
|
|
billName('Smith'); // "Bill Smith" |
|
billName('Clinton'); // "Bill Clinton" |
|
|
|
// Curry |
|
|
|
var fullName2 = fn.curry(function (firstName, middleName, lastName) { |
|
return firstName + ' ' + middleName + ' ' + lastName; |
|
}); |
|
|
|
var billName2 = fullName2('Bill'); |
|
|
|
billName2('Damon')('Smith'); // "Bill Damon Smith" |
|
billName2('Jefferson', 'Clinton'); // "Bill Jefferson Clinton" |
|
fullName2('Jenn', 'Anne', 'Cochran'); // "Jenn Anne Cochran" |
|
fullName2('Jenn', 'Anne')('Cochran'); // "Jenn Anne Cochran" |
|
|
|
// Curry right |
|
|
|
var fullName3 = fn.curryRight(function (firstName, middleName, lastName) { |
|
return firstName + ' ' + middleName + ' ' + lastName; |
|
}); |
|
|
|
var smithName = fullName3('Smith'); |
|
|
|
smithName('Damon')('Bill'); // "Bill Damon Smith" |
|
smithName('Jefferson', 'Bill'); // "Bill Jefferson Clinton" |
|
fullName3('Cochran', 'Anne', 'Jenn'); // "Jenn Anne Cochran" |
|
fullName3('Cochran', 'Anne')('Jenn'); // "Jenn Anne Cochran" |