1 // Various utility methods, primary for easy of functionals programming
  2 /*jslint white: false, onevar: false, plusplus: false */
  3 
  4 var nimbusly;
  5 if (nimbusly === undefined) { nimbusly = {}; }
  6 
  7 /**
  8  * Apply a method to each member of an array
  9  * 
 10  * @param f - A function taking a single value and returning a value
 11  */
 12 Array.prototype.each = function(f) {
 13     for (var i = 0; i < this.length; ++i) {
 14         f(this[i], i);
 15     }
 16 };
 17 
 18 Array.prototype.find = function(match) {
 19     for (var i = 0; i < this.length; ++i) {
 20         if (match(this[i])) {
 21             return this[i];
 22         }
 23     }
 24 };
 25 
 26 Array.prototype.map = function(f) {
 27     var result = new Array(this.length);
 28     for (var i = 0; i < this.length; ++i) {
 29         result[i] = f(this[i]);
 30     }
 31     return result;
 32 };
 33 
 34 /**
 35  * Apply a method to initial and the first value of the array, then to the result and the second, and
 36  * so on. For example, to sum the array, you could use:
 37  * 
 38  * [1, 4, 7].reduce(function(a,b) { return a+b }, 0)
 39  * 
 40  * @param op function to apply. It should take two parameters
 41  * @param initial Initial value. If left out, it won't be used
 42  */
 43 Array.prototype.reduce = function(op, initialValue) {
 44     var result = initialValue;
 45     var start = 0;
 46     if (!result) {
 47         if (this.length === 0) {
 48             return undefined;
 49         }
 50         result = this[0];
 51         start = 1;
 52     }
 53     for (var i = start; i < this.length; ++i) {
 54         result = op(result, this[i]);
 55     }
 56     return result;
 57 };
 58 
 59 Object.prototype.merge_in = function(hash) {
 60     for (var prop in hash) {
 61         if (hash.hasOwnProperty(prop)) {
 62             this[prop] = hash[prop];
 63         }
 64     }
 65     return this;
 66 };
 67 
 68 Object.prototype.merge = function(hash) {
 69     var result = {};
 70     result.merge_in(this).merge_in(hash);
 71     return result;
 72 };
 73 
 74 Function.prototype.curry = function() {
 75     var f = this;
 76     var appendArgs = function(a, b) {
 77         for (var i = 0; i < b.length; ++i) {
 78             a.push(b[i]);
 79         }
 80         return a;
 81     };
 82     var concatArgs = function(a, b) { 
 83         return appendArgs(appendArgs([], a), b); 
 84     };
 85     var curriedArgs = arguments;
 86     return function() { 
 87         return f.apply(this, concatArgs(curriedArgs, arguments)); 
 88     };
 89 };
 90 
 91 Function.prototype.andThen = function(g) {
 92     var f = this;
 93     return function() { f.apply(this, arguments); g.apply(this, arguments); };
 94 };
 95 
 96 Function.prototype.compose = function(g) {
 97     var f = this;
 98     return function() { return f(g.apply(this, arguments)); };
 99 };
100 
101 /**
102  * Given a function f(args.., callback), and a function g(args.., callback), f.callsback(g)
103  * will return a new function h(arg.., callback), that combines the calls to f and g.
104  */
105 Function.prototype.callsback = function(g) {
106     toArray = function(args) {
107         var result = [];
108         for (var i = 0; i < args.length; ++i) {
109             result.push(args[i]);
110         }
111         return result;
112     };
113 
114     var f = this;
115     return function() {
116         var callback = arguments[arguments.length-1]; 
117         var gCallback = function() { 
118             var newArgs = toArray(arguments);
119             newArgs.push(callback);
120             g.apply(this, newArgs); 
121         };
122         var args = toArray(arguments).slice(0, -1);
123         args.push(gCallback);        
124         return f.apply(this, args); 
125     }
126 }
127 
128 /**
129  * Generate a random integer between 0 and max-1
130  */
131 Math.randomInt = function(limit) {
132     return Math.floor(Math.random() * limit);
133 };
134 
135 /**
136  * Method to convert a list of functions into a has to return as a prototype object
137  */
138 nimbusly.log = function(message) {
139 //    console.log(message);
140 };
141 
142 /**
143  * Converts an object and method anme into a callback that will run the method in the context to the object
144  */
145 Function.prototype.makeCallback = function(obj) {
146     var method = this;
147     return function() { return method.apply(obj, arguments); }
148 };
149 
150