/** * Copyright 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS-IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @fileOverview A collection of core JavaScript utilities. */ /** * Iterator convenience for JavaScript Objects. * * Note that if func returns false, the iteration will be immediately terminated. * (Returning undefined, or not specifying a return type, does not terminate the iteration). * * @example var pastels = { red: "#fcc", green: "#cfc", blue: "#ccf" }; eachProperty(pastels, function(key, value) { print(DIV({style: 'background: '+value+';'}, key)); }); * * @param {object} obj The object over which to iterate. * @param {function} func The function to run on each [key,value] pair. */ function eachProperty(obj, func) { var r; for (k in obj) { if (!obj.hasOwnProperty || obj.hasOwnProperty(k)) { r = func(k,obj[k]); if (r === false) { break; } } } } /** * Douglas Crockford's "object" function for prototypal inheritance, taken from * http://javascript.crockford.com/prototypal.html * * @param {object} parent The parent object. * @return {object} A new object whose prototype is parent. */ function object(parent) { function f() {}; f.prototype = parent; return new f(); } /** * Creates an array of the properties of obj, * not including built-in or inherited properties. If no * argument is given, applies to the global object. * * @example // Prints "abc" keys({a: 1, b: 2, c: 3}).forEach(function(k) { print(k); } * * @example // Prints all the functions and object members of the global "appjet" object, // one per line. print(keys(appjet).join('\n')); * * @param {object} obj */ function keys(obj) { var array = []; var o = obj; if (o == undefined) { o = this; } for(var k in o) { if (!obj.hasOwnProperty || o.hasOwnProperty(k)) { array.push(k); } } return array; } /** * Comparator that returns -1, +1, or 0 depending on whether a < b, or a > b, or * neither, respectively. * @param {object} a * @param {object} b * @return {number} -1, 0, or +1 */ function cmp(a,b) { if (a < b) { return -1; } if (a > b) { return 1; } return 0; } function arrayToSet(arr) { var set = {}; arr.forEach(function(x) { set[x] = true; }); return set; } function mergeArrays(mergeFunction, a1, a2, etc) { var len = a1.length; var arrays = Array.prototype.slice.call(arguments, 1); for (var i = 0; i < arrays.length; ++i) { if (arrays[i].length != len) { return; } } out = []; for (var i = 0; i < a1.length; ++i) { out.push(mergeFunction.apply(this, arrays.map(function(array) { return array[i]; }))); } return out; } function debug(obj) { if (typeof(obj) == 'object') { var ret = []; if (obj) { eachProperty(obj, function(k, v) { ret.push(k+" -> "+debug(v)); }); return '['+ret.join(", ")+']'; } else { return String(obj); } } else { return String(obj); } } /** * Create a scala function out of the given JS function. */ function scalaFn(nargs, f) { if (typeof(f) == 'function') { return new Packages.scala['Function'+nargs]({ apply: f }); } else { return new Packages.scala['Function'+nargs]({ apply: function() { return f; } }) } } function scalaF0(f) { return scalaFn(0, f); } function scalaF1(f) { return scalaFn(1, f); } /** * Some bonus functions for functional programming. */ function f_curry(thisPtr, f, arg1, arg2, etc) { var curriedArgs = Array.prototype.slice.call(arguments, 2); return function() { var args = Array.prototype.slice.call(arguments, 0); return f.apply(thisPtr, curriedArgs.concat(args)); } } function f_limitArgs(thisPtr, f, n) { return function() { var args = Array.prototype.slice.call(arguments, 0, n); return f.apply(thisPtr, args); } }