diff options
Diffstat (limited to 'tools/addon-sdk-1.7/packages/api-utils/lib/functional.js')
-rw-r--r-- | tools/addon-sdk-1.7/packages/api-utils/lib/functional.js | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/tools/addon-sdk-1.7/packages/api-utils/lib/functional.js b/tools/addon-sdk-1.7/packages/api-utils/lib/functional.js new file mode 100644 index 0000000..61738d9 --- /dev/null +++ b/tools/addon-sdk-1.7/packages/api-utils/lib/functional.js @@ -0,0 +1,159 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Disclaimer: Most of the functions in this module implement APIs from +// Jeremy Ashkenas's http://underscorejs.org/ library and all credits for +// those goes to him. + +"use strict"; + +const { setTimeout } = require("./timer"); + +/** + * Takes `lambda` function and returns a method. When returned method is + * invoked it calls wrapped `lambda` and passes `this` as a first argument + * and given argument as rest. + */ +function method(lambda) { + return function method() { + return lambda.apply(null, [this].concat(Array.slice(arguments))); + } +} +exports.method = method; + +/** + * Takes a function and returns a wrapped one instead, calling which will call + * original function in the next turn of event loop. This is basically utility + * to do `setTimeout(function() { ... }, 0)`, with a difference that returned + * function is reused, instead of creating a new one each time. This also allows + * to use this functions as event listeners. + */ +function defer(f) { + return function deferred() + setTimeout(invoke, 0, f, arguments, this); +} +exports.defer = defer; +// Exporting `remit` alias as `defer` may conflict with promises. +exports.remit = defer; + +/** + * Invokes `callee` by passing `params` as an arguments and `self` as `this` + * pseudo-variable. Returns value that is returned by a callee. + * @param {Function} callee + * Function to invoke. + * @param {Array} params + * Arguments to invoke function with. + * @param {Object} self + * Object to be passed as a `this` pseudo variable. + */ +function invoke(callee, params, self) callee.apply(self, params); +exports.invoke = invoke; + +/** + * Curries a function with the arguments given. + * + * @param {Function} fn + * The function to curry + * + * @returns The function curried + */ +function curry(fn) { + if (typeof fn !== "function") + throw new TypeError(String(fn) + " is not a function"); + + let args = Array.slice(arguments, 1); + + return function() fn.apply(this, args.concat(Array.slice(arguments))); +} +exports.curry = curry; + +/** + * Returns the composition of a list of functions, where each function consumes + * the return value of the function that follows. In math terms, composing the + * functions `f()`, `g()`, and `h()` produces `f(g(h()))`. + * @example + * + * var greet = function(name) { return "hi: " + name; }; + * var exclaim = function(statement) { return statement + "!"; }; + * var welcome = compose(exclaim, greet); + * + * welcome('moe'); // => 'hi: moe!' + */ +function compose() { + let lambdas = Array.slice(arguments); + return function composed() { + let args = Array.slice(arguments), index = lambdas.length; + while (0 <= --index) + args = [ lambdas[index].apply(this, args) ]; + return args[0]; + }; +} +exports.compose = compose; + +/* + * Returns the first function passed as an argument to the second, + * allowing you to adjust arguments, run code before and after, and + * conditionally execute the original function. + * @example + * + * var hello = function(name) { return "hello: " + name; }; + * hello = wrap(hello, function(f) { + * return "before, " + f("moe") + ", after"; + * }); + * + * hello(); // => 'before, hello: moe, after' + */ +function wrap(f, wrapper) { + return function wrapped() + wrapper.apply(this, [ f ].concat(Array.slice(arguments))) +}; +exports.wrap = wrap; + +/** + * Returns the same value that is used as the argument. In math: f(x) = x + */ +function identity(value) value +exports.identity = identity; + +/** + * Memoizes a given function by caching the computed result. Useful for + * speeding up slow-running computations. If passed an optional hashFunction, + * it will be used to compute the hash key for storing the result, based on + * the arguments to the original function. The default hashFunction just uses + * the first argument to the memoized function as the key. + */ +function memoize(f, hasher) { + let memo = Object.create(null); + hasher = hasher || identity; + return function memoizer() { + let key = hasher.apply(this, arguments); + return key in memo ? memo[key] : (memo[key] = f.apply(this, arguments)); + }; +} +exports.memoize = memoize; + +/** + * Much like setTimeout, invokes function after wait milliseconds. If you pass + * the optional arguments, they will be forwarded on to the function when it is + * invoked. + */ +function delay(f, ms) { + let args = Array.slice(arguments, 2); + setTimeout(function(context) { return f.apply(context, args); }, ms, this); +}; +exports.delay = delay; + +/** + * Creates a version of the function that can only be called one time. Repeated + * calls to the modified function will have no effect, returning the value from + * the original call. Useful for initialization functions, instead of having to + * set a boolean flag and then check it later. + */ +function once(f) { + let ran = false, cache; + return function() ran ? cache : (ran = true, cache = f.apply(this, arguments)) +}; +exports.once = once; +// export cache as once will may be conflicting with event once a lot. +exports.cache = once; |