@rimbu/common 0.9.4 → 0.10.2

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/src/reducer.ts CHANGED
@@ -12,21 +12,6 @@ function identity<T>(value: T): T {
12
12
  }
13
13
 
14
14
  export namespace Reducer {
15
- /**
16
- * Ensures that all non-primitive type use lazy initialization to prevent accidental instance sharing.
17
- */
18
- // eslint-disable-next-line @typescript-eslint/ban-types
19
- export type Init<T> = T extends object | (() => any) ? () => T : T;
20
-
21
- /**
22
- * Returns the contained value for an `Init` instance.
23
- * @param init - the `Init` value container
24
- */
25
- export function Init<T>(init: Reducer.Init<T>): T {
26
- if (init instanceof Function) return init();
27
- return init as T;
28
- }
29
-
30
15
  /**
31
16
  * The Implementation interface for a `Reducer`, which also exposes the internal state type.
32
17
  * @typeparam I - the input value type
@@ -37,7 +22,7 @@ export namespace Reducer {
37
22
  /**
38
23
  * The initial state value for the reducer algorithm.
39
24
  */
40
- readonly init: Reducer.Init<S>;
25
+ readonly init: OptLazy<S>;
41
26
  /**
42
27
  * Returns the next state based on the given input values
43
28
  * @param state - the current state
@@ -68,6 +53,7 @@ export namespace Reducer {
68
53
  ): Reducer<I, O>;
69
54
  /**
70
55
  * Returns a `Reducer` instance that converts its input values using given `mapFun` before passing them to the reducer.
56
+ * @typeparam I2 - the resulting reducer input type
71
57
  * @param mapFun - a function that returns a new value to pass to the reducer based on the following inputs:<br/>
72
58
  * - value: the current input value<br/>
73
59
  * - index: the current input index
@@ -80,6 +66,7 @@ export namespace Reducer {
80
66
  mapInput<I2>(mapFun: (value: I2, index: number) => I): Reducer<I2, O>;
81
67
  /**
82
68
  * Returns a `Reducer` instance that converts or filters its input values using given `collectFun` before passing them to the reducer.
69
+ * @typeparam I2 - the resulting reducer input type
83
70
  * @param collectFun - a function receiving<br/>
84
71
  * - `value`: the next value<br/>
85
72
  * - `index`: the value index<br/>
@@ -95,6 +82,7 @@ export namespace Reducer {
95
82
  collectInput<I2>(collectFun: CollectFun<I2, I>): Reducer<I2, O>;
96
83
  /**
97
84
  * Returns a `Reducer` instance that converts its output values using given `mapFun`.
85
+ * @typeparam O2 - the resulting reducer output type
98
86
  * @param mapFun - a function that takes the current output value and converts it to a new output value
99
87
  * @example
100
88
  * ```ts
@@ -144,7 +132,7 @@ export namespace Reducer {
144
132
  */
145
133
  export class Base<I, O, S> implements Reducer.Impl<I, O, S> {
146
134
  constructor(
147
- readonly init: Reducer.Init<S>,
135
+ readonly init: OptLazy<S>,
148
136
  readonly next: (state: S, elem: I, index: number, halt: () => void) => S,
149
137
  readonly stateToResult: (state: S) => O
150
138
  ) {}
@@ -155,7 +143,7 @@ export namespace Reducer {
155
143
  return create(
156
144
  (): { state: S; nextIndex: number } => ({
157
145
  nextIndex: 0,
158
- state: Init(this.init),
146
+ state: OptLazy(this.init),
159
147
  }),
160
148
  (state, elem, index, halt): { state: S; nextIndex: number } => {
161
149
  if (pred(elem, index, halt)) {
@@ -180,7 +168,7 @@ export namespace Reducer {
180
168
  return create(
181
169
  (): { state: S; nextIndex: number } => ({
182
170
  nextIndex: 0,
183
- state: Init(this.init),
171
+ state: OptLazy(this.init),
184
172
  }),
185
173
  (state, elem, index, halt): { state: S; nextIndex: number } => {
186
174
  const nextElem = collectFun(elem, index, CollectFun.Skip, halt);
@@ -259,7 +247,7 @@ export namespace Reducer {
259
247
  * ```
260
248
  */
261
249
  export function create<I, O = I, S = O>(
262
- init: Reducer.Init<S>,
250
+ init: OptLazy<S>,
263
251
  next: (current: S, next: I, index: number, halt: () => void) => S,
264
252
  stateToResult: (state: S) => O
265
253
  ): Reducer<I, O> {
@@ -289,7 +277,7 @@ export namespace Reducer {
289
277
  * ```
290
278
  */
291
279
  export function createMono<T>(
292
- init: Reducer.Init<T>,
280
+ init: OptLazy<T>,
293
281
  next: (current: T, next: T, index: number, halt: () => void) => T,
294
282
  stateToResult?: (state: T) => T
295
283
  ): Reducer<T> {
@@ -320,7 +308,7 @@ export namespace Reducer {
320
308
  * ```
321
309
  */
322
310
  export function createOutput<I, O = I>(
323
- init: Reducer.Init<O>,
311
+ init: OptLazy<O>,
324
312
  next: (current: O, next: I, index: number, halt: () => void) => O,
325
313
  stateToResult?: (state: O) => O
326
314
  ): Reducer<I, O> {
@@ -630,8 +618,8 @@ export namespace Reducer {
630
618
  * @typeparam O - the fallback value type
631
619
  * @example
632
620
  * ```ts
633
- * console.log(Stream.range{ amount: 10 }).reduce(Reducer.first())
634
- * // => 0
621
+ * console.log(Stream.range{ amount: 10 }).reduce(Reducer.last())
622
+ * // => 9
635
623
  * ```
636
624
  */
637
625
  export const last: {
@@ -641,7 +629,7 @@ export namespace Reducer {
641
629
  const token = Symbol();
642
630
 
643
631
  return create<T, T | O, T | typeof token>(
644
- token,
632
+ () => token,
645
633
  (_, next): T => next,
646
634
  (state): T | O => (token === state ? OptLazy(otherwise!) : state)
647
635
  );
@@ -649,6 +637,7 @@ export namespace Reducer {
649
637
 
650
638
  /**
651
639
  * Returns a `Reducer` that ouputs false as long as no input value satisfies given `pred`, true otherwise.
640
+ * @typeparam T - the element type
652
641
  * @param pred - a function taking an input value and its index, and returning true if the value satisfies the predicate
653
642
  * @example
654
643
  * ```ts
@@ -673,6 +662,7 @@ export namespace Reducer {
673
662
 
674
663
  /**
675
664
  * Returns a `Reducer` that ouputs true as long as all input values satisfy the given `pred`, false otherwise.
665
+ * @typeparam T - the element type
676
666
  * @param pred - a function taking an input value and its index, and returning true if the value satisfies the predicate
677
667
  * @example
678
668
  * ```ts
@@ -698,6 +688,7 @@ export namespace Reducer {
698
688
 
699
689
  /**
700
690
  * Returns a `Reducer` that outputs false as long as the given `elem` has not been encountered in the input values, true otherwise.
691
+ * @typeparam T - the element type
701
692
  * @param elem - the element to search for
702
693
  * @param eq - (optional) a comparison function that returns true if te two given input values are considered equal
703
694
  * @example
@@ -784,6 +775,7 @@ export namespace Reducer {
784
775
 
785
776
  /**
786
777
  * Returns a `Reducer` that collects received input values in an array, and returns a copy of that array as an output value when requested.
778
+ * @typeparam T - the element type
787
779
  * @example
788
780
  * ```ts
789
781
  * console.log(Stream.of(1, 2, 3).reduce(Reducer.toArray()))
@@ -804,6 +796,8 @@ export namespace Reducer {
804
796
  /**
805
797
  * Returns a `Reducer` that collects received input tuples into a mutable JS Map, and returns
806
798
  * a copy of that map when output is requested.
799
+ * @typeparam K - the map key type
800
+ * @typeparam V - the map value type
807
801
  * @example
808
802
  * ```ts
809
803
  * console.log(Stream.of([1, 'a'], [2, 'b']).reduce(Reducer.toJSMap()))
@@ -824,6 +818,7 @@ export namespace Reducer {
824
818
  /**
825
819
  * Returns a `Reducer` that collects received input values into a mutable JS Set, and returns
826
820
  * a copy of that map when output is requested.
821
+ * @typeparam T - the element type
827
822
  * @example
828
823
  * ```ts
829
824
  * console.log(Stream.of(1, 2, 3).reduce(Reducer.toJSSet()))
@@ -841,6 +836,31 @@ export namespace Reducer {
841
836
  );
842
837
  }
843
838
 
839
+ /**
840
+ * Returns a `Reducer` that collects 2-tuples containing keys and values into a plain JS object, and
841
+ * returns a copy of that object when output is requested.
842
+ * @typeparam K - the result object key type
843
+ * @typeparam V - the result object value type
844
+ * @example
845
+ * ```ts
846
+ * console.log(Stream.of(['a', 1], ['b', true]).reduce(Reducer.toJSObject()))
847
+ * // { a: 1, b: true }
848
+ * ```
849
+ */
850
+ export function toJSObject<K extends string | number | symbol, V>(): Reducer<
851
+ [K, V],
852
+ Record<K, V>
853
+ > {
854
+ return create(
855
+ () => ({} as Record<K, V>),
856
+ (state, entry) => {
857
+ state[entry[0]] = entry[1];
858
+ return state;
859
+ },
860
+ (s) => ({ ...s })
861
+ );
862
+ }
863
+
844
864
  /**
845
865
  * Returns a `Reducer` that combines multiple input `reducers` by providing input values to all of them and collecting the outputs in an array.
846
866
  * @param reducers - 2 or more reducers to combine
@@ -870,7 +890,7 @@ export namespace Reducer {
870
890
  halt(): void {
871
891
  result.halted = true;
872
892
  },
873
- state: Init(reducer.init),
893
+ state: OptLazy(reducer.init),
874
894
  };
875
895
 
876
896
  return result;