# lib/goog/functions/functions.js

1 | // Copyright 2008 The Closure Library Authors. All Rights Reserved.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS-IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | /**
16 | * @fileoverview Utilities for creating functions. Loosely inspired by the
17 | * java classes: http://goo.gl/GM0Hmu and http://goo.gl/6k7nI8.
18 | *
19 | * @author nicksantos@google.com (Nick Santos)
20 | */
21 |
22 |
23 | goog.provide('goog.functions');
24 |
25 |
26 | /**
27 | * Creates a function that always returns the same value.
28 | * @param {T} retValue The value to return.
29 | * @return {function():T} The new function.
30 | * @template T
31 | */
32 | goog.functions.constant = function(retValue) {
33 | return function() {
34 | return retValue;
35 | };
36 | };
37 |
38 |
39 | /**
40 | * Always returns false.
41 | * @type {function(...): boolean}
42 | */
43 | goog.functions.FALSE = goog.functions.constant(false);
44 |
45 |
46 | /**
47 | * Always returns true.
48 | * @type {function(...): boolean}
49 | */
50 | goog.functions.TRUE = goog.functions.constant(true);
51 |
52 |
53 | /**
54 | * Always returns NULL.
55 | * @type {function(...): null}
56 | */
57 | goog.functions.NULL = goog.functions.constant(null);
58 |
59 |
60 | /**
61 | * A simple function that returns the first argument of whatever is passed
62 | * into it.
63 | * @param {T=} opt_returnValue The single value that will be returned.
64 | * @param {...*} var_args Optional trailing arguments. These are ignored.
65 | * @return {T} The first argument passed in, or undefined if nothing was passed.
66 | * @template T
67 | */
68 | goog.functions.identity = function(opt_returnValue, var_args) {
69 | return opt_returnValue;
70 | };
71 |
72 |
73 | /**
74 | * Creates a function that always throws an error with the given message.
75 | * @param {string} message The error message.
76 | * @return {!Function} The error-throwing function.
77 | */
78 | goog.functions.error = function(message) {
79 | return function() {
80 | throw Error(message);
81 | };
82 | };
83 |
84 |
85 | /**
86 | * Creates a function that throws the given object.
87 | * @param {*} err An object to be thrown.
88 | * @return {!Function} The error-throwing function.
89 | */
90 | goog.functions.fail = function(err) {
91 | return function() {
92 | throw err;
93 | }
94 | };
95 |
96 |
97 | /**
98 | * Given a function, create a function that keeps opt_numArgs arguments and
99 | * silently discards all additional arguments.
100 | * @param {Function} f The original function.
101 | * @param {number=} opt_numArgs The number of arguments to keep. Defaults to 0.
102 | * @return {!Function} A version of f that only keeps the first opt_numArgs
103 | * arguments.
104 | */
105 | goog.functions.lock = function(f, opt_numArgs) {
106 | opt_numArgs = opt_numArgs || 0;
107 | return function() {
108 | return f.apply(this, Array.prototype.slice.call(arguments, 0, opt_numArgs));
109 | };
110 | };
111 |
112 |
113 | /**
114 | * Creates a function that returns its nth argument.
115 | * @param {number} n The position of the return argument.
116 | * @return {!Function} A new function.
117 | */
118 | goog.functions.nth = function(n) {
119 | return function() {
120 | return arguments[n];
121 | };
122 | };
123 |
124 |
125 | /**
126 | * Given a function, create a new function that swallows its return value
127 | * and replaces it with a new one.
128 | * @param {Function} f A function.
129 | * @param {T} retValue A new return value.
130 | * @return {function(...[?]):T} A new function.
131 | * @template T
132 | */
133 | goog.functions.withReturnValue = function(f, retValue) {
134 | return goog.functions.sequence(f, goog.functions.constant(retValue));
135 | };
136 |
137 |
138 | /**
139 | * Creates a function that returns whether its arguement equals the given value.
140 | *
141 | * Example:
142 | * var key = goog.object.findKey(obj, goog.functions.equalTo('needle'));
143 | *
144 | * @param {*} value The value to compare to.
145 | * @param {boolean=} opt_useLooseComparison Whether to use a loose (==)
146 | * comparison rather than a strict (===) one. Defaults to false.
147 | * @return {function(*):boolean} The new function.
148 | */
149 | goog.functions.equalTo = function(value, opt_useLooseComparison) {
150 | return function(other) {
151 | return opt_useLooseComparison ? (value == other) : (value === other);
152 | };
153 | };
154 |
155 |
156 | /**
157 | * Creates the composition of the functions passed in.
158 | * For example, (goog.functions.compose(f, g))(a) is equivalent to f(g(a)).
159 | * @param {function(...[?]):T} fn The final function.
160 | * @param {...Function} var_args A list of functions.
161 | * @return {function(...[?]):T} The composition of all inputs.
162 | * @template T
163 | */
164 | goog.functions.compose = function(fn, var_args) {
165 | var functions = arguments;
166 | var length = functions.length;
167 | return function() {
168 | var result;
169 | if (length) {
170 | result = functions[length - 1].apply(this, arguments);
171 | }
172 |
173 | for (var i = length - 2; i >= 0; i--) {
174 | result = functions[i].call(this, result);
175 | }
176 | return result;
177 | };
178 | };
179 |
180 |
181 | /**
182 | * Creates a function that calls the functions passed in in sequence, and
183 | * returns the value of the last function. For example,
184 | * (goog.functions.sequence(f, g))(x) is equivalent to f(x),g(x).
185 | * @param {...Function} var_args A list of functions.
186 | * @return {!Function} A function that calls all inputs in sequence.
187 | */
188 | goog.functions.sequence = function(var_args) {
189 | var functions = arguments;
190 | var length = functions.length;
191 | return function() {
192 | var result;
193 | for (var i = 0; i < length; i++) {
194 | result = functions[i].apply(this, arguments);
195 | }
196 | return result;
197 | };
198 | };
199 |
200 |
201 | /**
202 | * Creates a function that returns true if each of its components evaluates
203 | * to true. The components are evaluated in order, and the evaluation will be
204 | * short-circuited as soon as a function returns false.
205 | * For example, (goog.functions.and(f, g))(x) is equivalent to f(x) && g(x).
206 | * @param {...Function} var_args A list of functions.
207 | * @return {function(...[?]):boolean} A function that ANDs its component
208 | * functions.
209 | */
210 | goog.functions.and = function(var_args) {
211 | var functions = arguments;
212 | var length = functions.length;
213 | return function() {
214 | for (var i = 0; i < length; i++) {
215 | if (!functions[i].apply(this, arguments)) {
216 | return false;
217 | }
218 | }
219 | return true;
220 | };
221 | };
222 |
223 |
224 | /**
225 | * Creates a function that returns true if any of its components evaluates
226 | * to true. The components are evaluated in order, and the evaluation will be
227 | * short-circuited as soon as a function returns true.
228 | * For example, (goog.functions.or(f, g))(x) is equivalent to f(x) || g(x).
229 | * @param {...Function} var_args A list of functions.
230 | * @return {function(...[?]):boolean} A function that ORs its component
231 | * functions.
232 | */
233 | goog.functions.or = function(var_args) {
234 | var functions = arguments;
235 | var length = functions.length;
236 | return function() {
237 | for (var i = 0; i < length; i++) {
238 | if (functions[i].apply(this, arguments)) {
239 | return true;
240 | }
241 | }
242 | return false;
243 | };
244 | };
245 |
246 |
247 | /**
248 | * Creates a function that returns the Boolean opposite of a provided function.
249 | * For example, (goog.functions.not(f))(x) is equivalent to !f(x).
250 | * @param {!Function} f The original function.
251 | * @return {function(...[?]):boolean} A function that delegates to f and returns
252 | * opposite.
253 | */
254 | goog.functions.not = function(f) {
255 | return function() {
256 | return !f.apply(this, arguments);
257 | };
258 | };
259 |
260 |
261 | /**
262 | * Generic factory function to construct an object given the constructor
263 | * and the arguments. Intended to be bound to create object factories.
264 | *
265 | * Example:
266 | *
267 | * var factory = goog.partial(goog.functions.create, Class);
268 | *
269 | * @param {function(new:T, ...)} constructor The constructor for the Object.
270 | * @param {...*} var_args The arguments to be passed to the constructor.
271 | * @return {!T} A new instance of the class given in {@code constructor}.
272 | * @template T
273 | */
274 | goog.functions.create = function(constructor, var_args) {
275 | /**
276 | * @constructor
277 | * @final
278 | */
279 | var temp = function() {};
280 | temp.prototype = constructor.prototype;
281 |
282 | // obj will have constructor's prototype in its chain and
283 | // 'obj instanceof constructor' will be true.
284 | var obj = new temp();
285 |
286 | // obj is initialized by constructor.
287 | // arguments is only array-like so lacks shift(), but can be used with
288 | // the Array prototype function.
289 | constructor.apply(obj, Array.prototype.slice.call(arguments, 1));
290 | return obj;
291 | };
292 |
293 |
294 | /**
295 | * @define {boolean} Whether the return value cache should be used.
296 | * This should only be used to disable caches when testing.
297 | */
298 | goog.define('goog.functions.CACHE_RETURN_VALUE', true);
299 |
300 |
301 | /**
302 | * Gives a wrapper function that caches the return value of a parameterless
303 | * function when first called.
304 | *
305 | * When called for the first time, the given function is called and its
306 | * return value is cached (thus this is only appropriate for idempotent
307 | * functions). Subsequent calls will return the cached return value. This
308 | * allows the evaluation of expensive functions to be delayed until first used.
309 | *
310 | * To cache the return values of functions with parameters, see goog.memoize.
311 | *
312 | * @param {!function():T} fn A function to lazily evaluate.
313 | * @return {!function():T} A wrapped version the function.
314 | * @template T
315 | */
316 | goog.functions.cacheReturnValue = function(fn) {
317 | var called = false;
318 | var value;
319 |
320 | return function() {
321 | if (!goog.functions.CACHE_RETURN_VALUE) {
322 | return fn();
323 | }
324 |
325 | if (!called) {
326 | value = fn();
327 | called = true;
328 | }
329 |
330 | return value;
331 | }
332 | };