text: // 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.
   */
  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 silently discards all additional
   * arguments.
   * @param {Function} f The original function.
   * @return {!Function} A version of f that discards its arguments.
   */
  goog.functions.lock = function(f) {
    return function() {
      return f.call(this);
    };
  };
  
  
  /**
   * 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.and(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 contructor.
   * @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 intialized 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;
  };
  