trie-memoize
Version:
A memoization algorithm in which each function argument represents a new key, creating a trie of caches as defined by the array in your first argument.
1 lines • 3.76 kB
Source Map (JSON)
{"version":3,"file":"index.mjs","sources":["../../src/index.ts"],"sourcesContent":["export interface MapLike {\n new (...args: any[]): any\n}\n\nexport type CacheConstructor =\n | MapConstructor\n | WeakMapConstructor\n | MapLike\n | Record<any, any>\n\ninterface Cache<K = any, V = any> {\n set: (k: K, v: V) => V\n get: (k: K) => V\n}\n\nconst createCache = (obj: CacheConstructor): Cache => {\n try {\n // @ts-ignore\n return new obj()\n } catch (e) {\n const cache: Record<string, any> = {}\n\n return {\n set(k, v): void {\n cache[k] = v\n },\n get(k): any {\n return cache[k]\n },\n }\n }\n}\n\nconst memo = (\n constructors: CacheConstructor[]\n): {s: Cache['set']; g: Cache['get']} => {\n const depth = constructors.length,\n baseCache = createCache(constructors[0])\n let base: any\n let map: any\n let i: number\n let node: typeof baseCache\n const one = depth === 1\n // quicker access for one and two-argument functions\n const g1 = (args: IArguments): any =>\n (base = baseCache.get(args[0])) === void 0 || one ? base : base.get(args[1])\n const s1 = (args: IArguments, value: any): any => {\n if (one) baseCache.set(args[0], value)\n else {\n if ((base = baseCache.get(args[0])) === void 0) {\n map = createCache(constructors[1])\n map.set(args[1], value)\n baseCache.set(args[0], map)\n } else {\n base.set(args[1], value)\n }\n }\n\n return value\n }\n\n const g2 = (args: IArguments): any => {\n node = baseCache\n\n for (i = 0; i < depth; i++)\n if ((node = node.get(args[i])) === void 0) return\n\n return node\n }\n\n const s2 = (args: IArguments, value: any): any => {\n node = baseCache\n\n for (i = 0; i < depth - 1; i++) {\n if ((map = node.get(args[i])) === void 0) {\n map = createCache(constructors[i + 1])\n node.set(args[i], map)\n node = map\n } else {\n node = map\n }\n }\n\n node.set(args[depth - 1], value)\n return value\n }\n\n return depth < 3 ? {g: g1, s: s1} : {g: g2, s: s2}\n}\n\nconst memoize = <T extends any[], U extends any>(\n mapConstructors: CacheConstructor[],\n fn: (...args: T) => U\n): ((...args: T) => U) => {\n let item: U\n const {g, s} = memo(mapConstructors)\n return function () {\n return (item = g(arguments)) === void 0\n ? s(arguments, fn.apply(null, arguments as any))\n : item\n }\n}\n\nexport default memoize\n"],"names":["createCache","obj","e","cache","set","k","v","get","mapConstructors","fn","item","constructors","base","map","i","node","depth","baseCache","one","g","s","length","args","value","arguments","apply"],"mappings":"AAeA,IAAMA,EAAeC,eAGV,IAAIA,EACX,MAAOC,OACDC,EAA6B,SAE5B,CACLC,IAAIC,EAAGC,GACLH,EAAME,GAAKC,GAEbC,IAAIF,GACKF,EAAME,oBA+DL,CACdG,EACAC,SAEIC,EA5DJC,EAIIC,EACAC,EACAC,EACAC,EALEC,EACJC,EAKIC,GAqDAC,EAACA,EAADC,EAAIA,IA3DJJ,GAFNL,EA6DoBH,GA3DOa,OACzBJ,EAAYjB,EAAYW,EAAa,IAKjCO,EAAgB,IAAVF,EA6CG,EAARA,EAAY,CAACG,EA3CRG,QAC0B,KAAnCV,EAAOK,EAAUV,IAAIe,EAAK,MAAmBJ,EAAMN,EAAOA,EAAKL,IAAIe,EAAK,IA0ChDF,EAzChB,CAACE,EAAkBC,KACxBL,EAAKD,EAAUb,IAAIkB,EAAK,GAAIC,QAEU,KAAnCX,EAAOK,EAAUV,IAAIe,EAAK,OAC7BT,EAAMb,EAAYW,EAAa,KAC3BP,IAAIkB,EAAK,GAAIC,GACjBN,EAAUb,IAAIkB,EAAK,GAAIT,IAEvBD,EAAKR,IAAIkB,EAAK,GAAIC,GAIfA,IA6B2B,CAACJ,EA1BzBG,QACVP,EAAOE,EAEFH,EAAI,EAAOE,EAAJF,EAAWA,YACc,KAA9BC,EAAOA,EAAKR,IAAIe,EAAKR,KAAiB,cAEtCC,GAoBmCK,EAjBjC,CAACE,EAAkBC,SAC5BR,EAAOE,EAEFH,EAAI,EAAOE,EAAQ,EAAZF,EAAeA,SACS,KAA7BD,EAAME,EAAKR,IAAIe,EAAKR,MACvBD,EAAMb,EAAYW,EAAaG,EAAI,IACnCC,EAAKX,IAAIkB,EAAKR,GAAID,GAClBE,EAAOF,GAEPE,EAAOF,SAIXE,EAAKX,IAAIkB,EAAKN,EAAQ,GAAIO,GACnBA,YAYF,uBAC4B,KAAzBb,EAAOS,EAAEK,YACbJ,EAAEI,UAAWf,EAAGgB,MAAM,KAAMD,YAC5Bd"}