123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- // function utils
- import { lruQueue } from './lruQueue.js';
- /**
- * Memoize a given function by caching the computed result.
- * The cache of a memoized function can be cleared by deleting the `cache`
- * property of the function.
- *
- * @param {function} fn The function to be memoized.
- * Must be a pure function.
- * @param {Object} [options]
- * @param {function(args: Array): string} [options.hasher]
- * A custom hash builder. Is JSON.stringify by default.
- * @param {number | undefined} [options.limit]
- * Maximum number of values that may be cached. Undefined indicates
- * unlimited (default)
- * @return {function} Returns the memoized function
- */
- export function memoize(fn) {
- var {
- hasher,
- limit
- } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
- limit = limit == null ? Number.POSITIVE_INFINITY : limit;
- hasher = hasher == null ? JSON.stringify : hasher;
- return function memoize() {
- if (typeof memoize.cache !== 'object') {
- memoize.cache = {
- values: new Map(),
- lru: lruQueue(limit || Number.POSITIVE_INFINITY)
- };
- }
- var args = [];
- for (var i = 0; i < arguments.length; i++) {
- args[i] = arguments[i];
- }
- var hash = hasher(args);
- if (memoize.cache.values.has(hash)) {
- memoize.cache.lru.hit(hash);
- return memoize.cache.values.get(hash);
- }
- var newVal = fn.apply(fn, args);
- memoize.cache.values.set(hash, newVal);
- memoize.cache.values.delete(memoize.cache.lru.hit(hash));
- return newVal;
- };
- }
- /**
- * Memoize a given function by caching all results and the arguments,
- * and comparing against the arguments of previous results before
- * executing again.
- * This is less performant than `memoize` which calculates a hash,
- * which is very fast to compare. Use `memoizeCompare` only when it is
- * not possible to create a unique serializable hash from the function
- * arguments.
- * The isEqual function must compare two sets of arguments
- * and return true when equal (can be a deep equality check for example).
- * @param {function} fn
- * @param {function(a: *, b: *) : boolean} isEqual
- * @returns {function}
- */
- export function memoizeCompare(fn, isEqual) {
- var memoize = function memoize() {
- var args = [];
- for (var i = 0; i < arguments.length; i++) {
- args[i] = arguments[i];
- }
- for (var c = 0; c < memoize.cache.length; c++) {
- var cached = memoize.cache[c];
- if (isEqual(args, cached.args)) {
- // TODO: move this cache entry to the top so recently used entries move up?
- return cached.res;
- }
- }
- var res = fn.apply(fn, args);
- memoize.cache.unshift({
- args,
- res
- });
- return res;
- };
- memoize.cache = [];
- return memoize;
- }
- /**
- * Find the maximum number of arguments expected by a typed function.
- * @param {function} fn A typed function
- * @return {number} Returns the maximum number of expected arguments.
- * Returns -1 when no signatures where found on the function.
- */
- export function maxArgumentCount(fn) {
- return Object.keys(fn.signatures || {}).reduce(function (args, signature) {
- var count = (signature.match(/,/g) || []).length + 1;
- return Math.max(args, count);
- }, -1);
- }
|