// Copyright 2008 The Closure Library Authors. All Rights Reserved. // // 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 Utilities for creating functions. Loosely inspired by the * java classes: http://go/functions.java and http://go/predicate.java. * * @author nicksantos@google.com (Nick Santos) */ goog.provide('goog.functions'); /** * Creates a function that always returns the same value. * @param {*} retValue The value to return. * @return {!Function} The new function. */ goog.functions.constant = function(retValue) { return function() { return retValue; }; }; /** * Always returns false. * @type {function(...): boolean} */ goog.functions.FALSE = goog.functions.constant(false); /** * Always returns true. * @type {function(...): boolean} */ goog.functions.TRUE = goog.functions.constant(true); /** * Always returns NULL. * @type {function(...): null} */ goog.functions.NULL = goog.functions.constant(null); /** * A simple function that returns the first argument of whatever is passed * into it. * @param {*=} opt_returnValue The single value that will be returned. * @param {...*} var_args Optional trailing arguments. These are ignored. * @return {?} The first argument passed in, or undefined if nothing was passed. * We can't know the type -- just pass it along without type. */ goog.functions.identity = function(opt_returnValue, var_args) { return opt_returnValue; }; /** * Creates a function that always throws an error with the given message. * @param {string} message The error message. * @return {!Function} The error-throwing function. */ goog.functions.error = function(message) { return function() { throw Error(message); }; }; /** * Given a function, create a function that keeps opt_numArgs arguments and * silently discards all additional arguments. * @param {Function} f The original function. * @param {number=} opt_numArgs The number of arguments to keep. Defaults to 0. * @return {!Function} A version of f that only keeps the first opt_numArgs * arguments. */ goog.functions.lock = function(f, opt_numArgs) { opt_numArgs = opt_numArgs || 0; return function() { return f.apply(this, Array.prototype.slice.call(arguments, 0, opt_numArgs)); }; }; /** * Given a function, create a new function that swallows its return value * and replaces it with a new one. * @param {Function} f A function. * @param {*} retValue A new return value. * @return {!Function} A new function. */ goog.functions.withReturnValue = function(f, retValue) { return goog.functions.sequence(f, goog.functions.constant(retValue)); }; /** * Creates the composition of the functions passed in. * For example, (goog.functions.compose(f, g))(a) is equivalent to f(g(a)). * @param {...Function} var_args A list of functions. * @return {!Function} The composition of all inputs. */ goog.functions.compose = function(var_args) { var functions = arguments; var length = functions.length; return function() { var result; if (length) { result = functions[length - 1].apply(this, arguments); } for (var i = length - 2; i >= 0; i--) { result = functions[i].call(this, result); } return result; }; }; /** * Creates a function that calls the functions passed in in sequence, and * returns the value of the last function. For example, * (goog.functions.sequence(f, g))(x) is equivalent to f(x),g(x). * @param {...Function} var_args A list of functions. * @return {!Function} A function that calls all inputs in sequence. */ goog.functions.sequence = function(var_args) { var functions = arguments; var length = functions.length; return function() { var result; for (var i = 0; i < length; i++) { result = functions[i].apply(this, arguments); } return result; }; }; /** * Creates a function that returns true if each of its components evaluates * to true. The components are evaluated in order, and the evaluation will be * short-circuited as soon as a function returns false. * For example, (goog.functions.and(f, g))(x) is equivalent to f(x) && g(x). * @param {...Function} var_args A list of functions. * @return {!Function} A function that ANDs its component functions. */ goog.functions.and = function(var_args) { var functions = arguments; var length = functions.length; return function() { for (var i = 0; i < length; i++) { if (!functions[i].apply(this, arguments)) { return false; } } return true; }; }; /** * Creates a function that returns true if any of its components evaluates * to true. The components are evaluated in order, and the evaluation will be * short-circuited as soon as a function returns true. * For example, (goog.functions.or(f, g))(x) is equivalent to f(x) || g(x). * @param {...Function} var_args A list of functions. * @return {!Function} A function that ORs its component functions. */ goog.functions.or = function(var_args) { var functions = arguments; var length = functions.length; return function() { for (var i = 0; i < length; i++) { if (functions[i].apply(this, arguments)) { return true; } } return false; }; }; /** * Creates a function that returns the Boolean opposite of a provided function. * For example, (goog.functions.not(f))(x) is equivalent to !f(x). * @param {!Function} f The original function. * @return {!Function} A function that delegates to f and returns opposite. */ goog.functions.not = function(f) { return function() { return !f.apply(this, arguments); }; }; /** * Generic factory function to construct an object given the constructor * and the arguments. Intended to be bound to create object factories. * * Callers should cast the result to the appropriate type for proper type * checking by the compiler. * @param {!Function} constructor The constructor for the Object. * @param {...*} var_args The arguments to be passed to the constructor. * @return {!Object} A new instance of the class given in {@code constructor}. */ goog.functions.create = function(constructor, var_args) { /** @constructor */ var temp = function() {}; temp.prototype = constructor.prototype; // obj will have constructor's prototype in its chain and // 'obj instanceof constructor' will be true. var obj = new temp(); // obj is initialized by constructor. // arguments is only array-like so lacks shift(), but can be used with // the Array prototype function. constructor.apply(obj, Array.prototype.slice.call(arguments, 1)); return obj; };