@beenotung/tslib
Version: 
utils library in Typescript
90 lines (89 loc) • 2.61 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MemorizePool = void 0;
exports.memorize = memorize;
const map_map_1 = require("./map-map");
const reflection_1 = require("./reflection");
/**
 * @description support any arguments length, any data type arguments
 *   do not works for self-recursive functions
 *   unless it is wrapped when being constructed
 *
 *   Example that works:
 *
 *       const q = memorize((n: number) => n < 2 ? 1 : q(n - 1) + q(n - 2));
 *
 *   Example that do not works:
 *
 *       let f = (n: number) => n < 2 ? 1 : f(n - 1) + f(n - 2);
 *       f = memorize(f);
 *
 * */
function memorize(f) {
    /* length => ...args */
    const cache = new map_map_1.MapMap();
    return Object.assign((0, reflection_1.wrapFunction)(function () {
        let map = cache.getMap(arguments.length);
        for (let i = arguments.length - 1; i > 0; i--) {
            map = map.getMap(arguments[i]);
        }
        const last = arguments[0];
        if (map.has(last)) {
            return map.get(last);
        }
        const res = f.apply(null, arguments);
        if (res instanceof Promise) {
            res.catch(_error => {
                map.delete(last);
            });
        }
        map.set(last, res);
        return res;
    }, f.length, f.name), {
        clear: () => cache.clear(),
        cache,
        remove: function (..._args) {
            let map = cache.getMap(arguments.length);
            for (let i = arguments.length - 1; i > 0; i--) {
                map = map.getMap(arguments[i]);
            }
            const last = arguments[0];
            map.delete(last);
        },
    });
}
class MemorizePool {
    cache = new map_map_1.MapMap();
    get(args) {
        const map = this.getLastMap(args);
        const last = args[0];
        if (map.has(last)) {
            return [map.get(last)];
        }
        else {
            return undefined;
        }
    }
    set(args, res) {
        this.getLastMap(args).set(args[0], res);
    }
    getOrCalc(args, f) {
        const map = this.getLastMap(args);
        const last = args[0];
        if (map.has(last)) {
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            return map.get(last);
        }
        const res = f();
        map.set(last, res);
        return res;
    }
    getLastMap(args) {
        let map = this.cache.getMap(args.length);
        for (let i = args.length - 1; i > 0; i--) {
            map = map.getMap(args[i]);
        }
        return map;
    }
}
exports.MemorizePool = MemorizePool;