return { compare: compare, compose: compose, defined: defined, id: id, insert: insert, map: map, mapFilter: mapFilter, of: of, proj: proj }; function compare(on) { on = on || id; return function(a, b) { var va = on(a), vb = on(b); return va < vb ? -1 : (va > vb ? 1 : 0) }; } function compose(f, g) { return function() { return f(g.apply(null, arguments)); }; } function defined(x) { return x != undefined; } function id(x) { return x; } function insert(obj, t, comparer, min, max) { min = defined(min) ? min : 0; max = defined(max) ? max : t.length; comparer = comparer || compare(); if(max - min < 1) { return min; } var avg = Math.floor((max + min) / 2); if (compare(obj, t[avg]) < 0) { return insert(obj, t, compare, min, avg); } else { return insert(obj, t, compare, avg+1, max); } } function map(mapper, f) { return function() { var args = Array.prototype.map.call(arguments, mapper); return f.apply(null, args); } } function mapFilter(mapper, predicate) { return function(array) { return array.reduce(function(accumulator, elem) { var v = mapper(elem); return predicate(v) ? accumulator.concat(v) : accumulator; }, []); }; } function of(o) { return function(key) {return o[key];}; } function proj(key) { return function(o) {return o[key];}; }