@thi.ng/memoize 3.1.65 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2024-03-13T14:04:31Z
3
+ - **Last updated**: 2024-04-08T14:59:29Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
@@ -9,6 +9,33 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
9
9
  **Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
10
10
  and/or version bumps of transitive dependencies.
11
11
 
12
+ ## [3.3.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/memoize@3.3.0) (2024-04-08)
13
+
14
+ #### 🚀 Features
15
+
16
+ - add delay() wrapper ([d8f4733](https://github.com/thi-ng/umbrella/commit/d8f4733))
17
+ - migrated from [@thi.ng/compose](https://github.com/thi-ng/umbrella/tree/main/packages/compose) since conceptually better at home here
18
+ - add docs
19
+
20
+ #### ♻️ Refactoring
21
+
22
+ - rename `defonce()` => `defOnce()` ([08e876f](https://github.com/thi-ng/umbrella/commit/08e876f))
23
+ - deprecate old spelling
24
+
25
+ ## [3.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/memoize@3.2.0) (2024-03-27)
26
+
27
+ #### 🚀 Features
28
+
29
+ - add memoizeO() ([af2ead9](https://github.com/thi-ng/umbrella/commit/af2ead9))
30
+ - add memoize2/3/4O() ([8309236](https://github.com/thi-ng/umbrella/commit/8309236))
31
+
32
+ #### ♻️ Refactoring
33
+
34
+ - minor updates, use plain objects where possible ([f44be23](https://github.com/thi-ng/umbrella/commit/f44be23))
35
+ - update defOnce() & memoizeJ() to use Object.create(null) as default store
36
+ - update default args in others
37
+ - update docs
38
+
12
39
  ### [3.1.41](https://github.com/thi-ng/umbrella/tree/@thi.ng/memoize@3.1.41) (2023-11-09)
13
40
 
14
41
  #### ♻️ Refactoring
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [![Mastodon Follow](https://img.shields.io/mastodon/follow/109331703950160316?domain=https%3A%2F%2Fmastodon.thi.ng&style=social)](https://mastodon.thi.ng/@toxi)
8
8
 
9
9
  > [!NOTE]
10
- > This is one of 190 standalone projects, maintained as part
10
+ > This is one of 191 standalone projects, maintained as part
11
11
  > of the [@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo
12
12
  > and anti-framework.
13
13
  >
@@ -15,6 +15,7 @@
15
15
  > GitHub](https://github.com/sponsors/postspectacular). Thank you! ❤️
16
16
 
17
17
  - [About](#about)
18
+ - [Available memoization functions](#available-memoization-functions)
18
19
  - [Status](#status)
19
20
  - [Related packages](#related-packages)
20
21
  - [Installation](#installation)
@@ -32,7 +33,7 @@
32
33
  Function memoization with configurable caching.
33
34
 
34
35
  This package provides different function memoization implementations for
35
- functions with 1 or more arguments and custom result caching using ES6
36
+ functions with arbitrary arguments and custom result caching using ES6
36
37
  Map API like implementations. Unlike native ES6 Maps, **the
37
38
  implementations MUST support value, not just referential, equality
38
39
  semantics** (e.g. those provided by
@@ -42,6 +43,16 @@ or
42
43
  The latter also support automatically pruning of memoization caches,
43
44
  based on different strategies. See doc strings for further details.
44
45
 
46
+ ### Available memoization functions
47
+
48
+ - [defOnce()](https://docs.thi.ng/umbrella/memoize/functions/defOnce.html)
49
+ - [delay()](https://docs.thi.ng/umbrella/memoize/functions/delay.html)
50
+ - [doOnce()](https://docs.thi.ng/umbrella/memoize/functions/doOnce.html)
51
+ - [memoize()](https://docs.thi.ng/umbrella/memoize/functions/memoize.html)
52
+ - [memoize1()](https://docs.thi.ng/umbrella/memoize/functions/memoize1.html)
53
+ - [memoizeJ()](https://docs.thi.ng/umbrella/memoize/functions/memoizeJ.html)
54
+ - [memoizeO()](https://docs.thi.ng/umbrella/memoize/functions/memoizeO.html)
55
+
45
56
  ## Status
46
57
 
47
58
  **STABLE** - used in production
@@ -58,7 +69,13 @@ based on different strategies. See doc strings for further details.
58
69
  yarn add @thi.ng/memoize
59
70
  ```
60
71
 
61
- ES module import:
72
+ ESM import:
73
+
74
+ ```ts
75
+ import * as mem from "@thi.ng/memoize";
76
+ ```
77
+
78
+ Browser ESM import:
62
79
 
63
80
  ```html
64
81
  <script type="module" src="https://cdn.skypack.dev/@thi.ng/memoize"></script>
@@ -69,10 +86,10 @@ ES module import:
69
86
  For Node.js REPL:
70
87
 
71
88
  ```js
72
- const memoize = await import("@thi.ng/memoize");
89
+ const mem = await import("@thi.ng/memoize");
73
90
  ```
74
91
 
75
- Package sizes (brotli'd, pre-treeshake): ESM: 247 bytes
92
+ Package sizes (brotli'd, pre-treeshake): ESM: 518 bytes
76
93
 
77
94
  ## Dependencies
78
95
 
package/defonce.d.ts CHANGED
@@ -1,17 +1,23 @@
1
1
  import type { Fn0 } from "@thi.ng/api";
2
2
  /**
3
- * Lightweight named singleton factory, intended for hot-module
4
- * replacement situations. Takes a (preferably globally unique) `id` and
5
- * `factory` function. If there's no value defined for `id` yet, calls
6
- * `factory` to produce the singleton value and caches it. Returns
7
- * singleton value.
3
+ * Lightweight named singleton factory, intended for hot-module replacement
4
+ * situations. Takes a (preferably globally unique) `id` and `factory` function.
5
+ * If there's no value defined for `id` yet, calls `factory` to produce the
6
+ * singleton value and caches it. Returns singleton value.
8
7
  *
9
- * Note: All created values will remain in the private cache until the
10
- * JS process terminates or this module itself has been reloaded (though
11
- * the latter shouldn't happen in an HMR workflow).
8
+ * @remarks
9
+ * Note: All created values will remain in the private cache until the JS
10
+ * process terminates or this module itself has been reloaded (though the latter
11
+ * shouldn't happen in an HMR workflow).
12
+ *
13
+ * For more control over memory usage, consider using other memoize functions in
14
+ * this package with one of the available cache implementations from
15
+ * [thi.ng/cache](https://thi.ng/cache).
12
16
  *
13
17
  * @param id -
14
18
  * @param factory -
15
19
  */
20
+ export declare const defOnce: <T>(id: string, factory: Fn0<T>) => T;
21
+ /** @deprecated renamed to {@link defOnce} */
16
22
  export declare const defonce: <T>(id: string, factory: Fn0<T>) => T;
17
23
  //# sourceMappingURL=defonce.d.ts.map
package/defonce.js CHANGED
@@ -1,5 +1,7 @@
1
- const cache = {};
2
- const defonce = (id, factory) => cache.hasOwnProperty(id) ? cache[id] : cache[id] = factory();
1
+ const cache = /* @__PURE__ */ Object.create(null);
2
+ const defOnce = (id, factory) => id in cache ? cache[id] : cache[id] = factory();
3
+ const defonce = defOnce;
3
4
  export {
5
+ defOnce,
4
6
  defonce
5
7
  };
package/delay.d.ts ADDED
@@ -0,0 +1,43 @@
1
+ import type { Fn0, IDeref } from "@thi.ng/api";
2
+ /**
3
+ * Syntax sugar for {@link Delay} ctor. Wraps given no-arg function in a
4
+ * {@link Delay} value/memoization wrapper and returns it. The function result
5
+ * can later be obtained via `.deref()`. The function will only be called the
6
+ * first time `.deref()` is used and the result will be cached. Future deref's
7
+ * will then only return the cached value.
8
+ *
9
+ * @remarks
10
+ * Use {@link Delay#isRealized} to check if the function result is already
11
+ * available (i.e. if the function has already been called).
12
+ *
13
+ * @example
14
+ * ```ts tangle:../export/delay.ts
15
+ * import { delay } from "@thi.ng/memoize";
16
+ *
17
+ * const a = delay(() => {
18
+ * console.log("calculating answer...");
19
+ * return 42;
20
+ * });
21
+ *
22
+ * // the function will only be called now (and once)
23
+ * console.log("first:", a.deref());
24
+ * // calculating answer...
25
+ * // first: 42
26
+ *
27
+ * // now only returns cached result
28
+ * console.log("second:", a.deref());
29
+ * // second: 42
30
+ * ```
31
+ *
32
+ * @param body
33
+ */
34
+ export declare const delay: <T>(body: Fn0<T>) => Delay<T>;
35
+ export declare class Delay<T> implements IDeref<T> {
36
+ protected value: T;
37
+ protected body: Fn0<T>;
38
+ protected realized: boolean;
39
+ constructor(body: Fn0<T>);
40
+ deref(): T;
41
+ isRealized(): boolean;
42
+ }
43
+ //# sourceMappingURL=delay.d.ts.map
package/delay.js ADDED
@@ -0,0 +1,24 @@
1
+ const delay = (body) => new Delay(body);
2
+ class Delay {
3
+ value;
4
+ body;
5
+ realized;
6
+ constructor(body) {
7
+ this.body = body;
8
+ this.realized = false;
9
+ }
10
+ deref() {
11
+ if (!this.realized) {
12
+ this.value = this.body();
13
+ this.realized = true;
14
+ }
15
+ return this.value;
16
+ }
17
+ isRealized() {
18
+ return this.realized;
19
+ }
20
+ }
21
+ export {
22
+ Delay,
23
+ delay
24
+ };
package/do-once.js CHANGED
@@ -1,11 +1,8 @@
1
- const doOnce = (fn, cache) => {
2
- !cache && (cache = /* @__PURE__ */ new Map());
3
- return (x) => {
4
- if (!cache.has(x)) {
5
- cache.set(x, true);
6
- fn(x);
7
- }
8
- };
1
+ const doOnce = (fn, cache = /* @__PURE__ */ new Map()) => (x) => {
2
+ if (!cache.has(x)) {
3
+ cache.set(x, true);
4
+ fn(x);
5
+ }
9
6
  };
10
7
  export {
11
8
  doOnce
package/index.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  export * from "./api.js";
2
2
  export * from "./defonce.js";
3
+ export * from "./delay.js";
3
4
  export * from "./do-once.js";
4
5
  export * from "./memoize.js";
5
6
  export * from "./memoize1.js";
6
7
  export * from "./memoizej.js";
8
+ export * from "./memoizeo.js";
7
9
  //# sourceMappingURL=index.d.ts.map
package/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  export * from "./api.js";
2
2
  export * from "./defonce.js";
3
+ export * from "./delay.js";
3
4
  export * from "./do-once.js";
4
5
  export * from "./memoize.js";
5
6
  export * from "./memoize1.js";
6
7
  export * from "./memoizej.js";
8
+ export * from "./memoizeo.js";
package/memoize.d.ts CHANGED
@@ -6,10 +6,13 @@ import type { MapLike } from "./api.js";
6
6
  * memoized result of given args. Supports generics for up to 4 args (otherwise
7
7
  * untyped).
8
8
  *
9
+ * @remarks
9
10
  * **Important:** It only makes sense to use `Map` types which support value
10
11
  * (rather than object) equality, e.g. those provided by
11
12
  * [`thi.ng/associative`](https://thi.ng/associative). Using a native `Map` type
12
- * here will lead to memory leaks! Alternatively, use {@link memoizeJ}.
13
+ * here will lead to memory leaks!
14
+ *
15
+ * Also see {@link memoizeJ}, {@link memoize1}, {@link memoizeO}.
13
16
  *
14
17
  * @param fn -
15
18
  * @param cache -
package/memoize1.d.ts CHANGED
@@ -1,11 +1,16 @@
1
1
  import type { Fn } from "@thi.ng/api";
2
2
  import type { MapLike } from "./api.js";
3
3
  /**
4
- * Optimized memoization for single arg functions. If the function expects args
5
- * other than strings or numbers, you MUST provide a `Map` implementation which
6
- * supports value (rather than object) equality, e.g. one of those provided by
4
+ * Optimized memoization for single arg functions.
5
+ *
6
+ * @remarks
7
+ * If the function expects args other than strings or numbers, you MUST provide
8
+ * a `Map` implementation which supports value (rather than object) equality,
9
+ * e.g. one of those provided by
7
10
  * [`thi.ng/associative`](https://thi.ng/associative). Using a native `Map` type
8
- * here will lead to memory leaks! Alternatively, use {@link memoizeJ}.
11
+ * here will lead to memory leaks!
12
+ *
13
+ * Also see {@link memoizeO}, {@link memoizeJ}, {@link memoize}.
9
14
  *
10
15
  * @param fn -
11
16
  * @param cache -
package/memoize1.js CHANGED
@@ -1,9 +1,6 @@
1
- const memoize1 = (fn, cache) => {
2
- !cache && (cache = /* @__PURE__ */ new Map());
3
- return (x) => {
4
- let res;
5
- return cache.has(x) ? cache.get(x) : (cache.set(x, res = fn(x)), res);
6
- };
1
+ const memoize1 = (fn, cache = /* @__PURE__ */ new Map()) => (x) => {
2
+ let res;
3
+ return cache.has(x) ? cache.get(x) : (cache.set(x, res = fn(x)), res);
7
4
  };
8
5
  export {
9
6
  memoize1
package/memoizej.d.ts CHANGED
@@ -5,9 +5,12 @@ import type { Fn, Fn2, Fn3, Fn4, IObjectOf } from "@thi.ng/api";
5
5
  * memoized result for given args. Supports generics for up to 4 args
6
6
  * (otherwise untyped).
7
7
  *
8
+ * @remarks
8
9
  * **Important:** If the given args cannot be stringified, the user
9
10
  * function will ALWAYS be called (without caching result).
10
11
  *
12
+ * Also see {@link memoize}, {@link memoize1}, {@link memoizeO}.
13
+ *
11
14
  * @param fn -
12
15
  * @param cache -
13
16
  */
package/memoizej.js CHANGED
@@ -1,5 +1,4 @@
1
- function memoizeJ(fn, cache) {
2
- !cache && (cache = {});
1
+ function memoizeJ(fn, cache = /* @__PURE__ */ Object.create(null)) {
3
2
  return (...args) => {
4
3
  const key = JSON.stringify(args);
5
4
  if (key !== void 0) {
package/memoizeo.d.ts ADDED
@@ -0,0 +1,53 @@
1
+ import type { Fn, Fn2, Fn3, Fn4, NumOrString } from "@thi.ng/api";
2
+ /**
3
+ * The most minimalistic & fastest memoization function of this package. Similar
4
+ * to {@link memoize1}, but only supports numbers or strings as keys and uses a
5
+ * vanilla JS object as cache.
6
+ *
7
+ * @remarks
8
+ * Also see {@link memoize1}, {@link memoizeJ}, {@link memoize}.
9
+ *
10
+ * @example
11
+ * ```ts tangle:../export/memoizeo.ts
12
+ * import { memoizeO } from "@thi.ng/memoize";
13
+ *
14
+ * const test = memoizeO((x: number) => (console.log("exec", x), x * 10));
15
+ *
16
+ * console.log(test(1));
17
+ * // exec 1
18
+ * // 10
19
+ *
20
+ * console.log(test(1))
21
+ * // 10
22
+ *
23
+ * console.log(test(2));
24
+ * // exec 2
25
+ * // 20
26
+ * ```
27
+ *
28
+ * @param fn
29
+ * @param cache
30
+ */
31
+ export declare const memoizeO: <A extends NumOrString, B>(fn: Fn<A, B>, cache?: Record<NumOrString, B>) => (x: A) => B;
32
+ /**
33
+ * Like {@link memoizeO}, but for functions with 2 arguments.
34
+ *
35
+ * @param fn
36
+ * @param cache
37
+ */
38
+ export declare const memoize2O: <A extends NumOrString, B extends NumOrString, C>(fn: Fn2<A, B, C>, cache?: Record<string, C>) => (a: A, b: B) => C;
39
+ /**
40
+ * Like {@link memoizeO}, but for functions with 3 arguments.
41
+ *
42
+ * @param fn
43
+ * @param cache
44
+ */
45
+ export declare const memoize3O: <A extends NumOrString, B extends NumOrString, C extends NumOrString, D>(fn: Fn3<A, B, C, D>, cache?: Record<string, D>) => (a: A, b: B, c: C) => D;
46
+ /**
47
+ * Like {@link memoizeO}, but for functions with 4 arguments.
48
+ *
49
+ * @param fn
50
+ * @param cache
51
+ */
52
+ export declare const memoize4O: <A extends NumOrString, B extends NumOrString, C extends NumOrString, D extends NumOrString, E>(fn: Fn4<A, B, C, D, E>, cache?: Record<string, E>) => (a: A, b: B, c: C, d: D) => E;
53
+ //# sourceMappingURL=memoizeo.d.ts.map
package/memoizeo.js ADDED
@@ -0,0 +1,19 @@
1
+ const memoizeO = (fn, cache = /* @__PURE__ */ Object.create(null)) => (x) => x in cache ? cache[x] : cache[x] = fn(x);
2
+ const memoize2O = (fn, cache = /* @__PURE__ */ Object.create(null)) => (a, b) => {
3
+ const key = a + "-" + b;
4
+ return key in cache ? cache[key] : cache[key] = fn(a, b);
5
+ };
6
+ const memoize3O = (fn, cache = /* @__PURE__ */ Object.create(null)) => (a, b, c) => {
7
+ const key = a + "-" + b + "-" + c;
8
+ return key in cache ? cache[key] : cache[key] = fn(a, b, c);
9
+ };
10
+ const memoize4O = (fn, cache = /* @__PURE__ */ Object.create(null)) => (a, b, c, d) => {
11
+ const key = a + "-" + b + "-" + c + "-" + d;
12
+ return key in cache ? cache[key] : cache[key] = fn(a, b, c, d);
13
+ };
14
+ export {
15
+ memoize2O,
16
+ memoize3O,
17
+ memoize4O,
18
+ memoizeO
19
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/memoize",
3
- "version": "3.1.65",
3
+ "version": "3.3.0",
4
4
  "description": "Function memoization with configurable caching",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -36,14 +36,14 @@
36
36
  "tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts"
37
37
  },
38
38
  "dependencies": {
39
- "@thi.ng/api": "^8.9.30"
39
+ "@thi.ng/api": "^8.10.0"
40
40
  },
41
41
  "devDependencies": {
42
- "@microsoft/api-extractor": "^7.42.3",
43
- "esbuild": "^0.20.1",
42
+ "@microsoft/api-extractor": "^7.43.0",
43
+ "esbuild": "^0.20.2",
44
44
  "rimraf": "^5.0.5",
45
45
  "typedoc": "^0.25.12",
46
- "typescript": "^5.4.2"
46
+ "typescript": "^5.4.3"
47
47
  },
48
48
  "keywords": [
49
49
  "cache",
@@ -71,6 +71,9 @@
71
71
  "./defonce": {
72
72
  "default": "./defonce.js"
73
73
  },
74
+ "./delay": {
75
+ "default": "./delay.js"
76
+ },
74
77
  "./do-once": {
75
78
  "default": "./do-once.js"
76
79
  },
@@ -82,6 +85,9 @@
82
85
  },
83
86
  "./memoizej": {
84
87
  "default": "./memoizej.js"
88
+ },
89
+ "./memoizeo": {
90
+ "default": "./memoizeo.js"
85
91
  }
86
92
  },
87
93
  "thi.ng": {
@@ -90,5 +96,5 @@
90
96
  ],
91
97
  "year": 2018
92
98
  },
93
- "gitHead": "7f3fcbd6c0462b0ce45afa141fe163d1f297fd51\n"
99
+ "gitHead": "85ac4bd4d6d89f8e3689e2863d5bea0cecdb371c\n"
94
100
  }