Skip to content

Instantly share code, notes, and snippets.

@hemanth
Forked from kputnam/u.js
Created July 13, 2012 09:43
Show Gist options
  • Save hemanth/3103955 to your computer and use it in GitHub Desktop.
Save hemanth/3103955 to your computer and use it in GitHub Desktop.
Functional combinators in JavaScript
var u = (function() {
var id = function(x) { return x; }
, single = function(x) { return [x]; }
, constant = function(x) { return function() { return x; }}
, $ = function(f, x) { return f(x); };
var curried = function(f, n, args) {
return (args.length >= n)
? f.apply(null, args)
: function() { return curried(f, n, args.concat(slice(arguments))); }; };
var curry = function(f, n) { return (n <= 0) ? f : curried(f, n, []); }
, slice = function(args, n) { return Array.prototype.slice.call(args, n || 0); }
, apply = function() { return call(arguments); }
, method = function(name) { return ap(bind, attr(name)); }
, invoke = function(name) { return compose(call(slice(arguments, 1)), method(name)); }
, uncurry = function(f) { return function() { return _.reduce(arguments, $, f); }};
var ap = curry(function(f, g) { return function(x) { return f(x, g(x)); }}, 2)
, attr = curry(function(name, object) { return object[name]; }, 2)
, flip = curry(function(f, a, b) { return f(b, a); }, 3)
, call = curry(function(args, f) { return f.apply(null, slice(args)); }, 2)
, bind = curry(function(ctx, method) { return function() { return method.apply(ctx, slice(arguments)); }}, 2)
, compose = curry(function(f, g) { return function(x) { return f(g(x)); }}, 2);
return ({id: id, constant: constant, ap: ap, slice: slice, attr: attr, bind: bind, call: call,
flip: flip, apply: apply, compose: compose, method: method, curry: curry, invoke: invoke, uncurry: uncurry});
})();
var op = ({
'add': u.curry(function(x,y) { return x + y; }, 2)
, 'sub': u.curry(function(x,y) { return x - y; }, 2)
, 'mul': u.curry(function(x,y) { return x * y; }, 2)
, 'div': u.curry(function(x,y) { return x / y; }, 2)
, 'mod': u.curry(function(x,y) { return x % y; }, 2)
, 'eq': u.curry(function(x,y) { return x === y; }, 2)
, 'ne': u.curry(function(x,y) { return x !== y; }, 2)
, 'gt': u.curry(function(x,y) { return x > y; }, 2)
, 'lt': u.curry(function(x,y) { return x < y; }, 2)
, 'lte': u.curry(function(x,y) { return x <= y; }, 2)
, 'gte': u.curry(function(x,y) { return x >= y; }, 2)
, 'or': u.curry(function(x,y) { return x || y; }, 2)
, 'and': u.curry(function(x,y) { return x && y; }, 2)
, 'xor': u.curry(function(x,y) { return x !== y; }, 2)
, 'not': function(x) { return !x; }
, 'typeof': function(x) { return typeof x; }
, 'instanceof': function(x) { return function(y) { return x instanceof y; }}
});
// Where does 'x' occur in each element?
console.log(_.map(['xbc', 'dxf', 'ghx'], u.invoke('indexOf', 'x')))
// What's the remainder of each element divided by 3?
console.log(_.map([12345, 23456, 56789], u.flip(op.mod)(3)))
// What's the length of each element?
console.log(_.map(['abc', 'def', 'ghi'], u.attr('length')))
// Does anyone have an 'o'?
console.log(_.any(['xbc', 'dxf', 'ghx'], u.compose(op.ne(-1), u.invoke('indexOf', 'o'))))
@austindd
Copy link

Very cool. I may try to use this sometime!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment