@nlozgachev/pipelined 0.65.0 → 0.67.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/README.md +70 -57
- package/dist/{Core-BHN87zoB.mjs → Core-BCN6WRzp.mjs} +1038 -616
- package/dist/{Core-BDXRLmMa.cjs → Core-CfAL_21H.cjs} +1043 -621
- package/dist/{InternalTypes-DzDey5Do.d.ts → InternalTypes-C0F5jyVQ.d.ts} +1 -1
- package/dist/{InternalTypes-B1Lh9uw_.d.cts → InternalTypes-DxSlzrpu.d.cts} +1 -1
- package/dist/composition.d.cts +2 -2
- package/dist/composition.d.ts +2 -2
- package/dist/core.cjs +2 -2
- package/dist/core.d.cts +3 -3
- package/dist/core.d.ts +3 -3
- package/dist/core.mjs +2 -2
- package/dist/data.cjs +1040 -535
- package/dist/data.d.cts +497 -310
- package/dist/data.d.ts +497 -310
- package/dist/data.mjs +1040 -535
- package/dist/{index-Bs8En5LJ.d.cts → index-CTe9CCHY.d.cts} +3 -0
- package/dist/{index-Bs8En5LJ.d.ts → index-CTe9CCHY.d.ts} +3 -0
- package/dist/{index-B07Wr815.d.ts → index-CdzHrj62.d.ts} +792 -444
- package/dist/{index-DCK_VPog.d.cts → index-NYjtX7XS.d.cts} +792 -444
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.mjs +2 -2
- package/dist/types.cjs +5 -1
- package/dist/types.d.cts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.mjs +5 -1
- package/package.json +20 -19
package/dist/data.cjs
CHANGED
|
@@ -1,51 +1,94 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_Core = require("./Core-
|
|
2
|
+
const require_Core = require("./Core-CfAL_21H.cjs");
|
|
3
3
|
//#region src/Data/Arr.ts
|
|
4
4
|
let ArrMaybe;
|
|
5
5
|
(function(_ArrMaybe) {
|
|
6
|
-
const traverse = _ArrMaybe.traverse = (
|
|
7
|
-
const n =
|
|
6
|
+
const traverse = _ArrMaybe.traverse = (transform) => (items) => {
|
|
7
|
+
const n = items.length;
|
|
8
8
|
const result = new Array(n);
|
|
9
9
|
for (let i = 0; i < n; i++) {
|
|
10
|
-
const mapped =
|
|
10
|
+
const mapped = transform(items[i]);
|
|
11
11
|
if (mapped.kind === "None") return require_Core.Maybe.make.none();
|
|
12
12
|
result[i] = mapped.value;
|
|
13
13
|
}
|
|
14
14
|
return require_Core.Maybe.make.some(result);
|
|
15
15
|
};
|
|
16
|
-
_ArrMaybe.sequence = (
|
|
16
|
+
_ArrMaybe.sequence = (items) => traverse((item) => item)(items);
|
|
17
17
|
})(ArrMaybe || (ArrMaybe = {}));
|
|
18
18
|
let ArrResult;
|
|
19
19
|
(function(_ArrResult) {
|
|
20
|
-
const traverse = _ArrResult.traverse = (
|
|
21
|
-
const n =
|
|
20
|
+
const traverse = _ArrResult.traverse = (transform) => (items) => {
|
|
21
|
+
const n = items.length;
|
|
22
22
|
const result = new Array(n);
|
|
23
23
|
for (let i = 0; i < n; i++) {
|
|
24
|
-
const mapped =
|
|
24
|
+
const mapped = transform(items[i]);
|
|
25
25
|
if (mapped.kind === "Err") return mapped;
|
|
26
26
|
result[i] = mapped.value;
|
|
27
27
|
}
|
|
28
28
|
return require_Core.Result.make.ok(result);
|
|
29
29
|
};
|
|
30
|
-
_ArrResult.sequence = (
|
|
30
|
+
_ArrResult.sequence = (items) => traverse((item) => item)(items);
|
|
31
31
|
})(ArrResult || (ArrResult = {}));
|
|
32
|
+
let ArrValidation;
|
|
33
|
+
(function(_ArrValidation) {
|
|
34
|
+
const traverse = _ArrValidation.traverse = (transform) => (items) => {
|
|
35
|
+
const n = items.length;
|
|
36
|
+
const result = new Array(n);
|
|
37
|
+
const errors = [];
|
|
38
|
+
for (let i = 0; i < n; i++) {
|
|
39
|
+
const mapped = transform(items[i]);
|
|
40
|
+
if (require_Core.Validation.is.failed(mapped)) errors.push(...mapped.errors);
|
|
41
|
+
else if (errors.length === 0) result[i] = mapped.value;
|
|
42
|
+
}
|
|
43
|
+
return require_Core.isNonEmptyArr(errors) ? require_Core.Validation.make.failedAll(errors) : require_Core.Validation.make.passed(result);
|
|
44
|
+
};
|
|
45
|
+
_ArrValidation.sequence = (items) => traverse((item) => item)(items);
|
|
46
|
+
})(ArrValidation || (ArrValidation = {}));
|
|
32
47
|
let ArrTaskResult;
|
|
33
48
|
(function(_ArrTaskResult) {
|
|
34
|
-
const traverse = _ArrTaskResult.traverse = (
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
49
|
+
const traverse = _ArrTaskResult.traverse = (transform, options) => (items) => (signal) => require_Core.Deferred.from.Promise((async () => {
|
|
50
|
+
const concurrency = options?.concurrency;
|
|
51
|
+
const len = items.length;
|
|
52
|
+
if (concurrency === void 0 || concurrency <= 1 || len <= 1) {
|
|
53
|
+
const result = [];
|
|
54
|
+
for (const a of items) {
|
|
55
|
+
const r = await require_Core.Deferred.to.Promise(transform(a)(signal));
|
|
56
|
+
if (require_Core.Result.is.err(r)) return r;
|
|
57
|
+
result.push(r.value);
|
|
58
|
+
}
|
|
59
|
+
return require_Core.Result.make.ok(result);
|
|
40
60
|
}
|
|
41
|
-
return
|
|
61
|
+
return new Promise((resolve) => {
|
|
62
|
+
const results = new Array(len);
|
|
63
|
+
let nextIndex = 0;
|
|
64
|
+
let settled = false;
|
|
65
|
+
const worker = async () => {
|
|
66
|
+
while (nextIndex < len && !settled) {
|
|
67
|
+
const currentIndex = nextIndex++;
|
|
68
|
+
const r = await require_Core.Deferred.to.Promise(transform(items[currentIndex])(signal));
|
|
69
|
+
if (settled) return;
|
|
70
|
+
if (require_Core.Result.is.err(r)) {
|
|
71
|
+
settled = true;
|
|
72
|
+
resolve(r);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
results[currentIndex] = r.value;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
const workerCount = Math.min(concurrency, len);
|
|
79
|
+
const workers = [];
|
|
80
|
+
for (let i = 0; i < workerCount; i++) workers.push(worker());
|
|
81
|
+
Promise.all(workers).then(() => {
|
|
82
|
+
if (!settled) resolve(require_Core.Result.make.ok(results));
|
|
83
|
+
});
|
|
84
|
+
});
|
|
42
85
|
})());
|
|
43
|
-
_ArrTaskResult.sequence = (
|
|
86
|
+
_ArrTaskResult.sequence = (items) => traverse((item) => item)(items);
|
|
44
87
|
})(ArrTaskResult || (ArrTaskResult = {}));
|
|
45
88
|
let ArrTask;
|
|
46
89
|
(function(_ArrTask) {
|
|
47
|
-
const traverse = _ArrTask.traverse = (
|
|
48
|
-
_ArrTask.sequence = (
|
|
90
|
+
const traverse = _ArrTask.traverse = (transform, options) => (items) => require_Core.Task.all(items.map(transform), options);
|
|
91
|
+
_ArrTask.sequence = (items) => traverse((item) => item)(items);
|
|
49
92
|
_ArrTask.Result = ArrTaskResult;
|
|
50
93
|
})(ArrTask || (ArrTask = {}));
|
|
51
94
|
/**
|
|
@@ -75,96 +118,118 @@ let ArrTask;
|
|
|
75
118
|
/**
|
|
76
119
|
* Returns the first element of an array, or None if the array is empty.
|
|
77
120
|
*
|
|
121
|
+
* @see {@link last} for accessing the final element.
|
|
122
|
+
* @see {@link tail} for all elements except the first.
|
|
123
|
+
*
|
|
78
124
|
* @example
|
|
79
125
|
* ```ts
|
|
80
126
|
* Arr.head([1, 2, 3]); // Some(1)
|
|
81
127
|
* Arr.head([]); // None
|
|
82
128
|
* ```
|
|
83
129
|
*/
|
|
84
|
-
const head = (
|
|
130
|
+
const head = (items) => items.length > 0 ? require_Core.Maybe.make.some(items[0]) : require_Core.Maybe.make.none();
|
|
85
131
|
/**
|
|
86
132
|
* Returns the last element of an array, or None if the array is empty.
|
|
87
133
|
*
|
|
134
|
+
* @see {@link head} for accessing the first element.
|
|
135
|
+
* @see {@link init} for all elements except the last.
|
|
136
|
+
*
|
|
88
137
|
* @example
|
|
89
138
|
* ```ts
|
|
90
139
|
* Arr.last([1, 2, 3]); // Some(3)
|
|
91
140
|
* Arr.last([]); // None
|
|
92
141
|
* ```
|
|
93
142
|
*/
|
|
94
|
-
const last = (
|
|
143
|
+
const last = (items) => items.length > 0 ? require_Core.Maybe.make.some(items[items.length - 1]) : require_Core.Maybe.make.none();
|
|
95
144
|
/**
|
|
96
145
|
* Returns all elements except the first, or None if the array is empty.
|
|
97
146
|
*
|
|
147
|
+
* @see {@link head} for accessing the first element.
|
|
148
|
+
*
|
|
98
149
|
* @example
|
|
99
150
|
* ```ts
|
|
100
151
|
* Arr.tail([1, 2, 3]); // Some([2, 3])
|
|
101
152
|
* Arr.tail([]); // None
|
|
102
153
|
* ```
|
|
103
154
|
*/
|
|
104
|
-
const tail = (
|
|
155
|
+
const tail = (items) => items.length > 0 ? require_Core.Maybe.make.some(items.slice(1)) : require_Core.Maybe.make.none();
|
|
105
156
|
/**
|
|
106
157
|
* Returns all elements except the last, or None if the array is empty.
|
|
107
158
|
*
|
|
159
|
+
* @see {@link last} for accessing the final element.
|
|
160
|
+
*
|
|
108
161
|
* @example
|
|
109
162
|
* ```ts
|
|
110
163
|
* Arr.init([1, 2, 3]); // Some([1, 2])
|
|
111
164
|
* Arr.init([]); // None
|
|
112
165
|
* ```
|
|
113
166
|
*/
|
|
114
|
-
const init = (
|
|
167
|
+
const init = (items) => items.length > 0 ? require_Core.Maybe.make.some(items.slice(0, -1)) : require_Core.Maybe.make.none();
|
|
115
168
|
/**
|
|
116
169
|
* Returns the first element matching the predicate, or None.
|
|
117
170
|
*
|
|
171
|
+
* @see {@link findLast} for finding the last matching element.
|
|
172
|
+
* @see {@link findIndex} for obtaining the index of the first matching element.
|
|
173
|
+
*
|
|
118
174
|
* @example
|
|
119
175
|
* ```ts
|
|
120
176
|
* pipe([1, 2, 3, 4], Arr.findFirst(n => n > 2)); // Some(3)
|
|
121
177
|
* ```
|
|
122
178
|
*/
|
|
123
|
-
const findFirst = (predicate) => (
|
|
124
|
-
const idx =
|
|
125
|
-
return idx !== -1 ? require_Core.Maybe.make.some(
|
|
179
|
+
const findFirst = (predicate) => (items) => {
|
|
180
|
+
const idx = items.findIndex(predicate);
|
|
181
|
+
return idx !== -1 ? require_Core.Maybe.make.some(items[idx]) : require_Core.Maybe.make.none();
|
|
126
182
|
};
|
|
127
183
|
/**
|
|
128
184
|
* Returns the last element matching the predicate, or None.
|
|
129
185
|
*
|
|
186
|
+
* @see {@link findFirst} for finding the first matching element.
|
|
187
|
+
*
|
|
130
188
|
* @example
|
|
131
189
|
* ```ts
|
|
132
190
|
* pipe([1, 2, 3, 4], Arr.findLast(n => n > 2)); // Some(4)
|
|
133
191
|
* ```
|
|
134
192
|
*/
|
|
135
|
-
const findLast = (predicate) => (
|
|
136
|
-
for (let i =
|
|
193
|
+
const findLast = (predicate) => (items) => {
|
|
194
|
+
for (let i = items.length - 1; i >= 0; i--) if (predicate(items[i])) return require_Core.Maybe.make.some(items[i]);
|
|
137
195
|
return require_Core.Maybe.make.none();
|
|
138
196
|
};
|
|
139
197
|
/**
|
|
140
198
|
* Returns the index of the first element matching the predicate, or None.
|
|
141
199
|
*
|
|
200
|
+
* @see {@link findFirst} for finding the matching element value.
|
|
201
|
+
*
|
|
142
202
|
* @example
|
|
143
203
|
* ```ts
|
|
144
204
|
* pipe([1, 2, 3, 4], Arr.findIndex(n => n > 2)); // Some(2)
|
|
145
205
|
* ```
|
|
146
206
|
*/
|
|
147
|
-
const findIndex = (predicate) => (
|
|
148
|
-
const idx =
|
|
207
|
+
const findIndex = (predicate) => (items) => {
|
|
208
|
+
const idx = items.findIndex(predicate);
|
|
149
209
|
return idx !== -1 ? require_Core.Maybe.make.some(idx) : require_Core.Maybe.make.none();
|
|
150
210
|
};
|
|
151
211
|
/**
|
|
152
212
|
* Transforms each element of an array.
|
|
153
213
|
*
|
|
214
|
+
* @see {@link flatMap} for mapping and flattening arrays.
|
|
215
|
+
* @see {@link mapWithIndex} for mapping with element indices.
|
|
216
|
+
*
|
|
154
217
|
* @example
|
|
155
218
|
* ```ts
|
|
156
219
|
* pipe([1, 2, 3], Arr.map(n => n * 2)); // [2, 4, 6]
|
|
157
220
|
* ```
|
|
158
221
|
*/
|
|
159
|
-
const map$3 = (
|
|
160
|
-
const n =
|
|
222
|
+
const map$3 = (transform) => (items) => {
|
|
223
|
+
const n = items.length;
|
|
161
224
|
const result = new Array(n);
|
|
162
|
-
for (let i = 0; i < n; i++) result[i] =
|
|
225
|
+
for (let i = 0; i < n; i++) result[i] = transform(items[i]);
|
|
163
226
|
return result;
|
|
164
227
|
};
|
|
165
228
|
/**
|
|
166
229
|
* Transforms each element using both its value and its zero-based index.
|
|
167
230
|
*
|
|
231
|
+
* @see {@link map} for mapping without indices.
|
|
232
|
+
*
|
|
168
233
|
* @example
|
|
169
234
|
* ```ts
|
|
170
235
|
* pipe(
|
|
@@ -173,30 +238,34 @@ const map$3 = (f) => (data) => {
|
|
|
173
238
|
* ); // [{ position: 1, value: "a" }, { position: 2, value: "b" }, { position: 3, value: "c" }]
|
|
174
239
|
* ```
|
|
175
240
|
*/
|
|
176
|
-
const mapWithIndex = (
|
|
177
|
-
const n =
|
|
241
|
+
const mapWithIndex = (transform) => (items) => {
|
|
242
|
+
const n = items.length;
|
|
178
243
|
const result = new Array(n);
|
|
179
|
-
for (let i = 0; i < n; i++) result[i] =
|
|
244
|
+
for (let i = 0; i < n; i++) result[i] = transform(i, items[i]);
|
|
180
245
|
return result;
|
|
181
246
|
};
|
|
182
247
|
/**
|
|
183
248
|
* Filters elements that satisfy the predicate.
|
|
184
249
|
*
|
|
250
|
+
* @see {@link filterMap} for filtering and mapping simultaneously.
|
|
251
|
+
*
|
|
185
252
|
* @example
|
|
186
253
|
* ```ts
|
|
187
254
|
* pipe([1, 2, 3, 4], Arr.filter(n => n % 2 === 0)); // [2, 4]
|
|
188
255
|
* ```
|
|
189
256
|
*/
|
|
190
|
-
const filter$3 = (predicate) => (
|
|
191
|
-
const n =
|
|
257
|
+
const filter$3 = (predicate) => (items) => {
|
|
258
|
+
const n = items.length;
|
|
192
259
|
const result = [];
|
|
193
|
-
for (let i = 0; i < n; i++) if (predicate(
|
|
260
|
+
for (let i = 0; i < n; i++) if (predicate(items[i])) result.push(items[i]);
|
|
194
261
|
return result;
|
|
195
262
|
};
|
|
196
263
|
/**
|
|
197
264
|
* Maps each element to a Maybe and collects only the Some values.
|
|
198
265
|
* Combines map and filter in a single pass.
|
|
199
266
|
*
|
|
267
|
+
* @see {@link filter} for filtering with a boolean predicate.
|
|
268
|
+
*
|
|
200
269
|
* @example
|
|
201
270
|
* ```ts
|
|
202
271
|
* const parseNum = (s: string): Maybe<number> => {
|
|
@@ -207,10 +276,10 @@ const filter$3 = (predicate) => (data) => {
|
|
|
207
276
|
* pipe(["1", "abc", "3"], Arr.filterMap(parseNum)); // [1, 3]
|
|
208
277
|
* ```
|
|
209
278
|
*/
|
|
210
|
-
const filterMap$3 = (
|
|
279
|
+
const filterMap$3 = (transform) => (items) => {
|
|
211
280
|
const result = [];
|
|
212
|
-
for (let i = 0; i <
|
|
213
|
-
const mapped =
|
|
281
|
+
for (let i = 0; i < items.length; i++) {
|
|
282
|
+
const mapped = transform(items[i]);
|
|
214
283
|
if (mapped.kind === "Some") result.push(mapped.value);
|
|
215
284
|
}
|
|
216
285
|
return result;
|
|
@@ -220,50 +289,59 @@ const filterMap$3 = (f) => (data) => {
|
|
|
220
289
|
* First group contains elements that satisfy the predicate,
|
|
221
290
|
* second group contains the rest.
|
|
222
291
|
*
|
|
292
|
+
* @see {@link partitionMap} for partitioning with a Result function.
|
|
293
|
+
*
|
|
223
294
|
* @example
|
|
224
295
|
* ```ts
|
|
225
296
|
* pipe([1, 2, 3, 4], Arr.partition(n => n % 2 === 0)); // [[2, 4], [1, 3]]
|
|
226
297
|
* ```
|
|
227
298
|
*/
|
|
228
|
-
const partition = (predicate) => (
|
|
299
|
+
const partition = (predicate) => (items) => {
|
|
229
300
|
const pass = [];
|
|
230
301
|
const fail = [];
|
|
231
|
-
for (const
|
|
302
|
+
for (const item of items) (predicate(item) ? pass : fail).push(item);
|
|
232
303
|
return [pass, fail];
|
|
233
304
|
};
|
|
234
305
|
/**
|
|
235
306
|
* Narrows a list of Maybe values down to a list of their underlying values,
|
|
236
307
|
* discarding all None instances.
|
|
237
308
|
*
|
|
309
|
+
* @see {@link separate} for dividing Results into error and success arrays.
|
|
310
|
+
*
|
|
238
311
|
* @example
|
|
239
312
|
* ```ts
|
|
240
313
|
* Arr.compact([Maybe.make.some(1), Maybe.make.none(), Maybe.make.some(3)]); // [1, 3]
|
|
241
314
|
* ```
|
|
242
315
|
*/
|
|
243
|
-
const compact$2 = (
|
|
316
|
+
const compact$2 = (items) => {
|
|
244
317
|
const result = [];
|
|
245
|
-
for (const item of
|
|
318
|
+
for (const item of items) if (item.kind === "Some") result.push(item.value);
|
|
246
319
|
return result;
|
|
247
320
|
};
|
|
248
321
|
/**
|
|
249
322
|
* Separates an array of Result values into two separate lists of errors and successes.
|
|
250
323
|
* Returns a tuple containing `[errors, successes]`.
|
|
251
324
|
*
|
|
325
|
+
* @see {@link compact} for extracting Some values from Maybe instances.
|
|
326
|
+
*
|
|
252
327
|
* @example
|
|
253
328
|
* ```ts
|
|
254
329
|
* Arr.separate([Result.make.ok(1), Result.make.err("bad"), Result.make.ok(3)]); // [["bad"], [1, 3]]
|
|
255
330
|
* ```
|
|
256
331
|
*/
|
|
257
|
-
const separate = (
|
|
332
|
+
const separate = (items) => {
|
|
258
333
|
const errors = [];
|
|
259
334
|
const successes = [];
|
|
260
|
-
for (const item of
|
|
335
|
+
for (const item of items) if (item.kind === "Ok") successes.push(item.value);
|
|
261
336
|
else errors.push(item.error);
|
|
262
337
|
return [errors, successes];
|
|
263
338
|
};
|
|
264
339
|
/**
|
|
265
340
|
* Maps each element to a Result, and separates the results into a tuple of failures and successes.
|
|
266
341
|
*
|
|
342
|
+
* @see {@link partition} for partitioning with a boolean predicate.
|
|
343
|
+
* @see {@link partitionMaybe} for partitioning with a Maybe function.
|
|
344
|
+
*
|
|
267
345
|
* @example
|
|
268
346
|
* ```ts
|
|
269
347
|
* pipe(
|
|
@@ -272,11 +350,11 @@ const separate = (data) => {
|
|
|
272
350
|
* ); // [["odd: 1", "odd: 3"], [2, 4]]
|
|
273
351
|
* ```
|
|
274
352
|
*/
|
|
275
|
-
const partitionMap = (
|
|
353
|
+
const partitionMap = (transform) => (items) => {
|
|
276
354
|
const errors = [];
|
|
277
355
|
const successes = [];
|
|
278
|
-
for (const item of
|
|
279
|
-
const mapped =
|
|
356
|
+
for (const item of items) {
|
|
357
|
+
const mapped = transform(item);
|
|
280
358
|
if (mapped.kind === "Ok") successes.push(mapped.value);
|
|
281
359
|
else errors.push(mapped.error);
|
|
282
360
|
}
|
|
@@ -285,6 +363,8 @@ const partitionMap = (f) => (data) => {
|
|
|
285
363
|
/**
|
|
286
364
|
* Groups elements by a key function.
|
|
287
365
|
*
|
|
366
|
+
* @see {@link indexBy} for indexing elements into a Map.
|
|
367
|
+
*
|
|
288
368
|
* @example
|
|
289
369
|
* ```ts
|
|
290
370
|
* pipe(
|
|
@@ -293,27 +373,33 @@ const partitionMap = (f) => (data) => {
|
|
|
293
373
|
* ); // { a: ["apple", "avocado"], b: ["banana"] }
|
|
294
374
|
* ```
|
|
295
375
|
*/
|
|
296
|
-
const groupBy$2 = (
|
|
376
|
+
const groupBy$2 = (keySelector) => (items) => {
|
|
297
377
|
const result = {};
|
|
298
|
-
for (const
|
|
299
|
-
const key =
|
|
378
|
+
for (const item of items) {
|
|
379
|
+
const key = keySelector(item);
|
|
300
380
|
if (!result[key]) result[key] = [];
|
|
301
|
-
result[key].push(
|
|
381
|
+
result[key].push(item);
|
|
302
382
|
}
|
|
303
383
|
return result;
|
|
304
384
|
};
|
|
305
385
|
/**
|
|
306
386
|
* Removes duplicate elements using strict equality.
|
|
307
387
|
*
|
|
388
|
+
* @see {@link uniqBy} for deduplicating by a key projection.
|
|
389
|
+
* @see {@link uniqWith} for deduplicating with custom equality.
|
|
390
|
+
*
|
|
308
391
|
* @example
|
|
309
392
|
* ```ts
|
|
310
393
|
* Arr.uniq([1, 2, 2, 3, 1]); // [1, 2, 3]
|
|
311
394
|
* ```
|
|
312
395
|
*/
|
|
313
|
-
const uniq = (
|
|
396
|
+
const uniq = (items) => items.length <= 1 ? items : [...new Set(items)];
|
|
314
397
|
/**
|
|
315
398
|
* Removes duplicate elements by comparing the result of a key function.
|
|
316
399
|
*
|
|
400
|
+
* @see {@link uniq} for reference-equality deduplication.
|
|
401
|
+
* @see {@link uniqWith} for deduplicating with custom equality.
|
|
402
|
+
*
|
|
317
403
|
* @example
|
|
318
404
|
* ```ts
|
|
319
405
|
* pipe(
|
|
@@ -322,14 +408,14 @@ const uniq = (data) => data.length <= 1 ? data : [...new Set(data)];
|
|
|
322
408
|
* ); // [{id: 1, name: "a"}, {id: 2, name: "c"}]
|
|
323
409
|
* ```
|
|
324
410
|
*/
|
|
325
|
-
const uniqBy = (
|
|
411
|
+
const uniqBy = (keySelector) => (items) => {
|
|
326
412
|
const seen = /* @__PURE__ */ new Set();
|
|
327
413
|
const result = [];
|
|
328
|
-
for (const
|
|
329
|
-
const key =
|
|
414
|
+
for (const item of items) {
|
|
415
|
+
const key = keySelector(item);
|
|
330
416
|
if (!seen.has(key)) {
|
|
331
417
|
seen.add(key);
|
|
332
|
-
result.push(
|
|
418
|
+
result.push(item);
|
|
333
419
|
}
|
|
334
420
|
}
|
|
335
421
|
return result;
|
|
@@ -339,6 +425,9 @@ const uniqBy = (f) => (data) => {
|
|
|
339
425
|
* Preserves the order of first occurrences. Complements `uniq` (reference equality)
|
|
340
426
|
* and `uniqBy` (key extraction).
|
|
341
427
|
*
|
|
428
|
+
* @see {@link uniq} for reference-equality deduplication.
|
|
429
|
+
* @see {@link uniqBy} for key-based deduplication.
|
|
430
|
+
*
|
|
342
431
|
* @example
|
|
343
432
|
* ```ts
|
|
344
433
|
* type Point = { x: number; y: number };
|
|
@@ -350,29 +439,33 @@ const uniqBy = (f) => (data) => {
|
|
|
350
439
|
* ); // [{ x: 1, y: 1 }, { x: 2, y: 2 }]
|
|
351
440
|
* ```
|
|
352
441
|
*/
|
|
353
|
-
const uniqWith = (
|
|
442
|
+
const uniqWith = (areEqual) => (items) => {
|
|
354
443
|
const result = [];
|
|
355
|
-
for (const
|
|
444
|
+
for (const item of items) if (!result.some((existing) => areEqual(existing, item))) result.push(item);
|
|
356
445
|
return result;
|
|
357
446
|
};
|
|
358
447
|
/**
|
|
359
448
|
* Sorts an array using a comparison function. Returns a new array.
|
|
360
449
|
* To sort with a typed `Ordering<A>`, prefer `Arr.sortWith`.
|
|
361
450
|
*
|
|
451
|
+
* @see {@link sortWith} for sorting using typed Ordering instances.
|
|
452
|
+
*
|
|
362
453
|
* @example
|
|
363
454
|
* ```ts
|
|
364
455
|
* pipe([3, 1, 2], Arr.sortBy((a, b) => a - b)); // [1, 2, 3]
|
|
365
456
|
* ```
|
|
366
457
|
*/
|
|
367
|
-
const sortBy = (compare) => (
|
|
368
|
-
const arr =
|
|
458
|
+
const sortBy = (compare) => (items) => {
|
|
459
|
+
const arr = items;
|
|
369
460
|
if (typeof arr.toSorted === "function") return arr.toSorted(compare);
|
|
370
|
-
return [...
|
|
461
|
+
return [...items].sort(compare);
|
|
371
462
|
};
|
|
372
463
|
/**
|
|
373
464
|
* Sorts an array using an `Ordering<A>`. Returns a new array without mutating the original.
|
|
374
465
|
* Use this over `sortBy` when you have a typed `Ordering<A>` from the `Ordering` module.
|
|
375
466
|
*
|
|
467
|
+
* @see {@link sortBy} for sorting using a comparator function.
|
|
468
|
+
*
|
|
376
469
|
* @example
|
|
377
470
|
* ```ts
|
|
378
471
|
* pipe([3, 1, 2], Arr.sortWith(Ordering.number)); // [1, 2, 3]
|
|
@@ -383,37 +476,41 @@ const sortBy = (compare) => (data) => {
|
|
|
383
476
|
* pipe(products, Arr.sortWith(byPrice));
|
|
384
477
|
* ```
|
|
385
478
|
*/
|
|
386
|
-
const sortWith = (
|
|
387
|
-
const arr =
|
|
388
|
-
if (typeof arr.toSorted === "function") return arr.toSorted(
|
|
389
|
-
return [...
|
|
479
|
+
const sortWith = (ordering) => (items) => {
|
|
480
|
+
const arr = items;
|
|
481
|
+
if (typeof arr.toSorted === "function") return arr.toSorted(ordering);
|
|
482
|
+
return [...items].sort(ordering);
|
|
390
483
|
};
|
|
391
484
|
/**
|
|
392
485
|
* Pairs up elements from two arrays. Stops at the shorter array.
|
|
393
486
|
*
|
|
487
|
+
* @see {@link zipWith} for pairing elements with a custom combining function.
|
|
488
|
+
*
|
|
394
489
|
* @example
|
|
395
490
|
* ```ts
|
|
396
491
|
* pipe([1, 2, 3], Arr.zip(["a", "b"])); // [[1, "a"], [2, "b"]]
|
|
397
492
|
* ```
|
|
398
493
|
*/
|
|
399
|
-
const zip = (other) => (
|
|
400
|
-
const len = Math.min(
|
|
494
|
+
const zip = (other) => (items) => {
|
|
495
|
+
const len = Math.min(items.length, other.length);
|
|
401
496
|
const result = new Array(len);
|
|
402
|
-
for (let i = 0; i < len; i++) result[i] = [
|
|
497
|
+
for (let i = 0; i < len; i++) result[i] = [items[i], other[i]];
|
|
403
498
|
return result;
|
|
404
499
|
};
|
|
405
500
|
/**
|
|
406
501
|
* Combines elements from two arrays using a function. Stops at the shorter array.
|
|
407
502
|
*
|
|
503
|
+
* @see {@link zip} for pairing elements into 2-tuples.
|
|
504
|
+
*
|
|
408
505
|
* @example
|
|
409
506
|
* ```ts
|
|
410
507
|
* pipe([1, 2], Arr.zipWith((a: number, b: string) => `${a}${b}`)(["a", "b"])); // ["1a", "2b"]
|
|
411
508
|
* ```
|
|
412
509
|
*/
|
|
413
|
-
const zipWith = (
|
|
414
|
-
const len = Math.min(
|
|
510
|
+
const zipWith = (combine) => (other) => (items) => {
|
|
511
|
+
const len = Math.min(items.length, other.length);
|
|
415
512
|
const result = new Array(len);
|
|
416
|
-
for (let i = 0; i < len; i++) result[i] =
|
|
513
|
+
for (let i = 0; i < len; i++) result[i] = combine(items[i], other[i]);
|
|
417
514
|
return result;
|
|
418
515
|
};
|
|
419
516
|
/**
|
|
@@ -424,10 +521,10 @@ const zipWith = (f) => (other) => (data) => {
|
|
|
424
521
|
* pipe([1, 2, 3], Arr.intersperse(0)); // [1, 0, 2, 0, 3]
|
|
425
522
|
* ```
|
|
426
523
|
*/
|
|
427
|
-
const intersperse = (
|
|
428
|
-
if (
|
|
429
|
-
const result = [
|
|
430
|
-
for (let i = 1; i <
|
|
524
|
+
const intersperse = (separator) => (items) => {
|
|
525
|
+
if (items.length <= 1) return items;
|
|
526
|
+
const result = [items[0]];
|
|
527
|
+
for (let i = 1; i < items.length; i++) result.push(separator, items[i]);
|
|
431
528
|
return result;
|
|
432
529
|
};
|
|
433
530
|
/**
|
|
@@ -438,37 +535,41 @@ const intersperse = (sep) => (data) => {
|
|
|
438
535
|
* pipe([1, 2], Arr.concat([3, 4])); // [1, 2, 3, 4]
|
|
439
536
|
* ```
|
|
440
537
|
*/
|
|
441
|
-
const concat = (other) => (
|
|
538
|
+
const concat = (other) => (items) => [...items, ...other];
|
|
442
539
|
/**
|
|
443
540
|
* Splits an array into chunks of the given size.
|
|
444
541
|
*
|
|
542
|
+
* @see {@link chunkBy} for grouping consecutive elements sharing a key.
|
|
543
|
+
*
|
|
445
544
|
* @example
|
|
446
545
|
* ```ts
|
|
447
546
|
* pipe([1, 2, 3, 4, 5], Arr.chunksOf(2)); // [[1, 2], [3, 4], [5]]
|
|
448
547
|
* ```
|
|
449
548
|
*/
|
|
450
|
-
const chunksOf = (
|
|
451
|
-
if (
|
|
549
|
+
const chunksOf = (size) => (items) => {
|
|
550
|
+
if (size <= 0) return [];
|
|
452
551
|
const result = [];
|
|
453
|
-
for (let i = 0; i <
|
|
552
|
+
for (let i = 0; i < items.length; i += size) result.push(items.slice(i, i + size));
|
|
454
553
|
return result;
|
|
455
554
|
};
|
|
456
555
|
/**
|
|
457
556
|
* Flattens a nested array by one level.
|
|
458
557
|
*
|
|
558
|
+
* @see {@link flatMap} for mapping elements to arrays before flattening.
|
|
559
|
+
*
|
|
459
560
|
* @example
|
|
460
561
|
* ```ts
|
|
461
562
|
* Arr.flatten([[1, 2], [3], [4, 5]]); // [1, 2, 3, 4, 5]
|
|
462
563
|
* ```
|
|
463
564
|
*/
|
|
464
|
-
const flatten = (
|
|
565
|
+
const flatten = (items) => {
|
|
465
566
|
let totalLen = 0;
|
|
466
|
-
const outerLen =
|
|
467
|
-
for (let i = 0; i < outerLen; i++) totalLen +=
|
|
567
|
+
const outerLen = items.length;
|
|
568
|
+
for (let i = 0; i < outerLen; i++) totalLen += items[i].length;
|
|
468
569
|
const result = new Array(totalLen);
|
|
469
570
|
let idx = 0;
|
|
470
571
|
for (let i = 0; i < outerLen; i++) {
|
|
471
|
-
const chunk =
|
|
572
|
+
const chunk = items[i];
|
|
472
573
|
const innerLen = chunk.length;
|
|
473
574
|
for (let j = 0; j < innerLen; j++) result[idx++] = chunk[j];
|
|
474
575
|
}
|
|
@@ -477,16 +578,19 @@ const flatten = (data) => {
|
|
|
477
578
|
/**
|
|
478
579
|
* Maps each element to an array and flattens the result.
|
|
479
580
|
*
|
|
581
|
+
* @see {@link map} for mapping without flattening.
|
|
582
|
+
* @see {@link flatten} for flattening without mapping.
|
|
583
|
+
*
|
|
480
584
|
* @example
|
|
481
585
|
* ```ts
|
|
482
586
|
* pipe([1, 2, 3], Arr.flatMap(n => [n, n * 10])); // [1, 10, 2, 20, 3, 30]
|
|
483
587
|
* ```
|
|
484
588
|
*/
|
|
485
|
-
const flatMap = (
|
|
486
|
-
const n =
|
|
589
|
+
const flatMap = (transform) => (items) => {
|
|
590
|
+
const n = items.length;
|
|
487
591
|
const result = [];
|
|
488
592
|
for (let i = 0; i < n; i++) {
|
|
489
|
-
const chunk =
|
|
593
|
+
const chunk = transform(items[i]);
|
|
490
594
|
const m = chunk.length;
|
|
491
595
|
for (let j = 0; j < m; j++) result.push(chunk[j]);
|
|
492
596
|
}
|
|
@@ -495,32 +599,38 @@ const flatMap = (f) => (data) => {
|
|
|
495
599
|
/**
|
|
496
600
|
* Reduces an array from the left.
|
|
497
601
|
*
|
|
602
|
+
* @see {@link scan} for preserving intermediate accumulation states.
|
|
603
|
+
*
|
|
498
604
|
* @example
|
|
499
605
|
* ```ts
|
|
500
606
|
* pipe([1, 2, 3], Arr.reduce(0, (acc, n) => acc + n)); // 6
|
|
501
607
|
* ```
|
|
502
608
|
*/
|
|
503
|
-
const reduce$2 = (initial,
|
|
504
|
-
const _traverseTask = Object.assign((f) => ArrTask.traverse(f), { Result: ArrTaskResult.traverse });
|
|
609
|
+
const reduce$2 = (initial, reducer) => (items) => items.reduce(reducer, initial);
|
|
610
|
+
const _traverseTask = Object.assign((f, options) => ArrTask.traverse(f, options), { Result: ArrTaskResult.traverse });
|
|
505
611
|
const _sequenceTask = Object.assign((data) => ArrTask.sequence(data), { Result: ArrTaskResult.sequence });
|
|
506
612
|
/**
|
|
507
613
|
* Prepends a value to the beginning of an array, returning a NonEmptyArr.
|
|
508
614
|
*
|
|
615
|
+
* @see {@link append} for adding an element to the end.
|
|
616
|
+
*
|
|
509
617
|
* @example
|
|
510
618
|
* ```ts
|
|
511
619
|
* pipe([1, 2], Arr.prepend(0)); // [0, 1, 2]
|
|
512
620
|
* ```
|
|
513
621
|
*/
|
|
514
|
-
const prepend = (
|
|
622
|
+
const prepend = (item) => (items) => [item, ...items];
|
|
515
623
|
/**
|
|
516
624
|
* Appends a value to the end of an array, returning a NonEmptyArr.
|
|
517
625
|
*
|
|
626
|
+
* @see {@link prepend} for adding an element to the beginning.
|
|
627
|
+
*
|
|
518
628
|
* @example
|
|
519
629
|
* ```ts
|
|
520
630
|
* pipe([1, 2], Arr.append(3)); // [1, 2, 3]
|
|
521
631
|
* ```
|
|
522
632
|
*/
|
|
523
|
-
const append = (
|
|
633
|
+
const append = (item) => (items) => [...items, item];
|
|
524
634
|
/**
|
|
525
635
|
* Returns the length of an array.
|
|
526
636
|
*
|
|
@@ -529,31 +639,35 @@ const append = (value) => (data) => [...data, value];
|
|
|
529
639
|
* Arr.size([1, 2, 3]); // 3
|
|
530
640
|
* ```
|
|
531
641
|
*/
|
|
532
|
-
const size$3 = (
|
|
642
|
+
const size$3 = (items) => items.length;
|
|
533
643
|
/**
|
|
534
644
|
* Returns true if any element satisfies the predicate.
|
|
535
645
|
*
|
|
646
|
+
* @see {@link every} for checking whether all elements satisfy a predicate.
|
|
647
|
+
*
|
|
536
648
|
* @example
|
|
537
649
|
* ```ts
|
|
538
650
|
* pipe([1, 2, 3], Arr.some(n => n > 2)); // true
|
|
539
651
|
* ```
|
|
540
652
|
*/
|
|
541
|
-
const some = (predicate) => (
|
|
542
|
-
const n =
|
|
543
|
-
for (let i = 0; i < n; i++) if (predicate(
|
|
653
|
+
const some = (predicate) => (items) => {
|
|
654
|
+
const n = items.length;
|
|
655
|
+
for (let i = 0; i < n; i++) if (predicate(items[i])) return true;
|
|
544
656
|
return false;
|
|
545
657
|
};
|
|
546
658
|
/**
|
|
547
659
|
* Returns true if all elements satisfy the predicate.
|
|
548
660
|
*
|
|
661
|
+
* @see {@link some} for checking whether any element satisfies a predicate.
|
|
662
|
+
*
|
|
549
663
|
* @example
|
|
550
664
|
* ```ts
|
|
551
665
|
* pipe([1, 2, 3], Arr.every(n => n > 0)); // true
|
|
552
666
|
* ```
|
|
553
667
|
*/
|
|
554
|
-
const every = (predicate) => (
|
|
555
|
-
const n =
|
|
556
|
-
for (let i = 0; i < n; i++) if (!predicate(
|
|
668
|
+
const every = (predicate) => (items) => {
|
|
669
|
+
const n = items.length;
|
|
670
|
+
for (let i = 0; i < n; i++) if (!predicate(items[i])) return false;
|
|
557
671
|
return true;
|
|
558
672
|
};
|
|
559
673
|
/**
|
|
@@ -564,11 +678,13 @@ const every = (predicate) => (data) => {
|
|
|
564
678
|
* Arr.reverse([1, 2, 3]); // [3, 2, 1]
|
|
565
679
|
* ```
|
|
566
680
|
*/
|
|
567
|
-
const reverse = (
|
|
681
|
+
const reverse = (items) => [...items].toReversed();
|
|
568
682
|
/**
|
|
569
683
|
* Returns a new array with `item` inserted before the element at `index`.
|
|
570
684
|
* Negative indices are clamped to 0; indices beyond the array length append to the end.
|
|
571
685
|
*
|
|
686
|
+
* @see {@link removeAt} for removing an element at an index.
|
|
687
|
+
*
|
|
572
688
|
* @example
|
|
573
689
|
* ```ts
|
|
574
690
|
* pipe([1, 2, 3], Arr.insertAt(1, 99)); // [1, 99, 2, 3]
|
|
@@ -576,11 +692,11 @@ const reverse = (data) => [...data].toReversed();
|
|
|
576
692
|
* pipe([1, 2, 3], Arr.insertAt(3, 99)); // [1, 2, 3, 99]
|
|
577
693
|
* ```
|
|
578
694
|
*/
|
|
579
|
-
const insertAt = (index, item) => (
|
|
580
|
-
const i = Math.max(0, Math.min(index,
|
|
581
|
-
const arr =
|
|
695
|
+
const insertAt = (index, item) => (items) => {
|
|
696
|
+
const i = Math.max(0, Math.min(index, items.length));
|
|
697
|
+
const arr = items;
|
|
582
698
|
if (typeof arr.toSpliced === "function") return arr.toSpliced(i, 0, item);
|
|
583
|
-
const result = [...
|
|
699
|
+
const result = [...items];
|
|
584
700
|
result.splice(i, 0, item);
|
|
585
701
|
return result;
|
|
586
702
|
};
|
|
@@ -588,6 +704,8 @@ const insertAt = (index, item) => (data) => {
|
|
|
588
704
|
* Returns a new array with the element at `index` removed.
|
|
589
705
|
* Returns the original array unchanged if `index` is out of bounds.
|
|
590
706
|
*
|
|
707
|
+
* @see {@link insertAt} for inserting an element at an index.
|
|
708
|
+
*
|
|
591
709
|
* @example
|
|
592
710
|
* ```ts
|
|
593
711
|
* pipe([1, 2, 3], Arr.removeAt(1)); // [1, 3]
|
|
@@ -595,76 +713,90 @@ const insertAt = (index, item) => (data) => {
|
|
|
595
713
|
* pipe([1, 2, 3], Arr.removeAt(5)); // [1, 2, 3]
|
|
596
714
|
* ```
|
|
597
715
|
*/
|
|
598
|
-
const removeAt = (index) => (
|
|
599
|
-
if (index < 0 || index >=
|
|
600
|
-
const arr =
|
|
716
|
+
const removeAt = (index) => (items) => {
|
|
717
|
+
if (index < 0 || index >= items.length) return items;
|
|
718
|
+
const arr = items;
|
|
601
719
|
if (typeof arr.toSpliced === "function") return arr.toSpliced(index, 1);
|
|
602
|
-
const result = [...
|
|
720
|
+
const result = [...items];
|
|
603
721
|
result.splice(index, 1);
|
|
604
722
|
return result;
|
|
605
723
|
};
|
|
606
724
|
/**
|
|
607
725
|
* Takes the first n elements from an array.
|
|
608
726
|
*
|
|
727
|
+
* @see {@link drop} for discarding the first n elements.
|
|
728
|
+
* @see {@link takeWhile} for taking elements based on a predicate.
|
|
729
|
+
*
|
|
609
730
|
* @example
|
|
610
731
|
* ```ts
|
|
611
732
|
* pipe([1, 2, 3, 4], Arr.take(2)); // [1, 2]
|
|
612
733
|
* ```
|
|
613
734
|
*/
|
|
614
|
-
const take = (
|
|
735
|
+
const take = (count) => (items) => count <= 0 ? [] : items.slice(0, count);
|
|
615
736
|
/**
|
|
616
737
|
* Drops the first n elements from an array.
|
|
617
738
|
*
|
|
739
|
+
* @see {@link take} for keeping the first n elements.
|
|
740
|
+
* @see {@link dropWhile} for discarding elements based on a predicate.
|
|
741
|
+
*
|
|
618
742
|
* @example
|
|
619
743
|
* ```ts
|
|
620
744
|
* pipe([1, 2, 3, 4], Arr.drop(2)); // [3, 4]
|
|
621
745
|
* ```
|
|
622
746
|
*/
|
|
623
|
-
const drop = (
|
|
747
|
+
const drop = (count) => (items) => items.slice(count);
|
|
624
748
|
/**
|
|
625
749
|
* Takes elements from the start while the predicate holds.
|
|
626
750
|
*
|
|
751
|
+
* @see {@link dropWhile} for discarding elements while a predicate holds.
|
|
752
|
+
* @see {@link take} for taking a fixed count of elements.
|
|
753
|
+
*
|
|
627
754
|
* @example
|
|
628
755
|
* ```ts
|
|
629
756
|
* pipe([1, 2, 3, 1], Arr.takeWhile(n => n < 3)); // [1, 2]
|
|
630
757
|
* ```
|
|
631
758
|
*/
|
|
632
|
-
const takeWhile = (predicate) => (
|
|
759
|
+
const takeWhile = (predicate) => (items) => {
|
|
633
760
|
const result = [];
|
|
634
|
-
for (const
|
|
635
|
-
if (!predicate(
|
|
636
|
-
result.push(
|
|
761
|
+
for (const item of items) {
|
|
762
|
+
if (!predicate(item)) break;
|
|
763
|
+
result.push(item);
|
|
637
764
|
}
|
|
638
765
|
return result;
|
|
639
766
|
};
|
|
640
767
|
/**
|
|
641
768
|
* Drops elements from the start while the predicate holds.
|
|
642
769
|
*
|
|
770
|
+
* @see {@link takeWhile} for keeping elements while a predicate holds.
|
|
771
|
+
* @see {@link drop} for discarding a fixed count of elements.
|
|
772
|
+
*
|
|
643
773
|
* @example
|
|
644
774
|
* ```ts
|
|
645
775
|
* pipe([1, 2, 3, 1], Arr.dropWhile(n => n < 3)); // [3, 1]
|
|
646
776
|
* ```
|
|
647
777
|
*/
|
|
648
|
-
const dropWhile = (predicate) => (
|
|
778
|
+
const dropWhile = (predicate) => (items) => {
|
|
649
779
|
let i = 0;
|
|
650
|
-
while (i <
|
|
651
|
-
return
|
|
780
|
+
while (i < items.length && predicate(items[i])) i++;
|
|
781
|
+
return items.slice(i);
|
|
652
782
|
};
|
|
653
783
|
/**
|
|
654
784
|
* Like `reduce`, but returns every intermediate accumulator as an array.
|
|
655
785
|
* The initial value is not included — the output has the same length as the input.
|
|
656
786
|
*
|
|
787
|
+
* @see {@link reduce} for computing only the final accumulator value.
|
|
788
|
+
*
|
|
657
789
|
* @example
|
|
658
790
|
* ```ts
|
|
659
791
|
* pipe([1, 2, 3], Arr.scan(0, (acc, n) => acc + n)); // [1, 3, 6]
|
|
660
792
|
* ```
|
|
661
793
|
*/
|
|
662
|
-
const scan = (initial,
|
|
663
|
-
const n =
|
|
794
|
+
const scan = (initial, reducer) => (items) => {
|
|
795
|
+
const n = items.length;
|
|
664
796
|
const result = new Array(n);
|
|
665
797
|
let acc = initial;
|
|
666
798
|
for (let i = 0; i < n; i++) {
|
|
667
|
-
acc =
|
|
799
|
+
acc = reducer(acc, items[i]);
|
|
668
800
|
result[i] = acc;
|
|
669
801
|
}
|
|
670
802
|
return result;
|
|
@@ -680,28 +812,31 @@ const scan = (initial, f) => (data) => {
|
|
|
680
812
|
* pipe([1, 2, 3], Arr.splitAt(10)); // [[1, 2, 3], []]
|
|
681
813
|
* ```
|
|
682
814
|
*/
|
|
683
|
-
const splitAt = (index) => (
|
|
815
|
+
const splitAt = (index) => (items) => {
|
|
684
816
|
const i = Math.max(0, index);
|
|
685
|
-
return [
|
|
817
|
+
return [items.slice(0, i), items.slice(i)];
|
|
686
818
|
};
|
|
687
819
|
/**
|
|
688
820
|
* Partitions an array by applying a function returning `Maybe<B>`.
|
|
689
821
|
* Elements returning `None` are gathered into `failures` (original `A` values);
|
|
690
822
|
* elements returning `Some(b)` are gathered into `successes` (`B` values).
|
|
691
823
|
*
|
|
824
|
+
* @see {@link partitionMap} for partitioning with a Result mapper.
|
|
825
|
+
* @see {@link partition} for partitioning with a boolean predicate.
|
|
826
|
+
*
|
|
692
827
|
* @example
|
|
693
828
|
* ```ts
|
|
694
829
|
* const parseNumber = (s: string) => isNaN(Number(s)) ? Maybe.make.none() : Maybe.make.some(Number(s));
|
|
695
830
|
* pipe(["1", "abc", "3"], Arr.partitionMaybe(parseNumber)); // [["abc"], [1, 3]]
|
|
696
831
|
* ```
|
|
697
832
|
*/
|
|
698
|
-
const partitionMaybe = (
|
|
833
|
+
const partitionMaybe = (transform) => (items) => {
|
|
699
834
|
const failures = [];
|
|
700
835
|
const successes = [];
|
|
701
|
-
for (let i = 0; i <
|
|
702
|
-
const res =
|
|
836
|
+
for (let i = 0; i < items.length; i++) {
|
|
837
|
+
const res = transform(items[i]);
|
|
703
838
|
if (res.kind === "Some") successes.push(res.value);
|
|
704
|
-
else failures.push(
|
|
839
|
+
else failures.push(items[i]);
|
|
705
840
|
}
|
|
706
841
|
return [failures, successes];
|
|
707
842
|
};
|
|
@@ -716,13 +851,15 @@ const partitionMaybe = (f) => (data) => {
|
|
|
716
851
|
* pipe([10, 20, 30], Arr.at(5)); // None
|
|
717
852
|
* ```
|
|
718
853
|
*/
|
|
719
|
-
const at = (index) => (
|
|
720
|
-
const targetIndex = index < 0 ?
|
|
721
|
-
if (targetIndex < 0 || targetIndex >=
|
|
722
|
-
return require_Core.Maybe.make.some(
|
|
854
|
+
const at = (index) => (items) => {
|
|
855
|
+
const targetIndex = index < 0 ? items.length + index : index;
|
|
856
|
+
if (targetIndex < 0 || targetIndex >= items.length) return require_Core.Maybe.make.none();
|
|
857
|
+
return require_Core.Maybe.make.some(items[targetIndex]);
|
|
723
858
|
};
|
|
724
859
|
/**
|
|
725
|
-
* Finds the first element in an array for which `
|
|
860
|
+
* Finds the first element in an array for which `transform` returns `Some(b)`.
|
|
861
|
+
*
|
|
862
|
+
* @see {@link findFirst} for finding elements with a boolean predicate.
|
|
726
863
|
*
|
|
727
864
|
* @example
|
|
728
865
|
* ```ts
|
|
@@ -732,9 +869,9 @@ const at = (index) => (data) => {
|
|
|
732
869
|
* ); // Some(1)
|
|
733
870
|
* ```
|
|
734
871
|
*/
|
|
735
|
-
const findMap = (
|
|
736
|
-
for (let i = 0; i <
|
|
737
|
-
const res =
|
|
872
|
+
const findMap = (transform) => (items) => {
|
|
873
|
+
for (let i = 0; i < items.length; i++) {
|
|
874
|
+
const res = transform(items[i]);
|
|
738
875
|
if (res.kind === "Some") return res;
|
|
739
876
|
}
|
|
740
877
|
return require_Core.Maybe.make.none();
|
|
@@ -742,6 +879,8 @@ const findMap = (f) => (data) => {
|
|
|
742
879
|
/**
|
|
743
880
|
* Indexes elements of an array into a `ReadonlyMap<K, A>` using a key extraction function.
|
|
744
881
|
*
|
|
882
|
+
* @see {@link groupBy} for grouping multiple items per key into arrays.
|
|
883
|
+
*
|
|
745
884
|
* @example
|
|
746
885
|
* ```ts
|
|
747
886
|
* pipe(
|
|
@@ -750,9 +889,9 @@ const findMap = (f) => (data) => {
|
|
|
750
889
|
* ); // ReadonlyMap { 1 => { id: 1, name: "Alice" }, 2 => { id: 2, name: "Bob" } }
|
|
751
890
|
* ```
|
|
752
891
|
*/
|
|
753
|
-
const indexBy = (
|
|
892
|
+
const indexBy = (keySelector) => (items) => {
|
|
754
893
|
const resultMap = new globalThis.Map();
|
|
755
|
-
for (let i = 0; i <
|
|
894
|
+
for (let i = 0; i < items.length; i++) resultMap.set(keySelector(items[i]), items[i]);
|
|
756
895
|
return resultMap;
|
|
757
896
|
};
|
|
758
897
|
/**
|
|
@@ -764,16 +903,18 @@ const indexBy = (keyFn) => (data) => {
|
|
|
764
903
|
* // ReadonlyMap { "a" => 3, "b" => 2, "c" => 1 }
|
|
765
904
|
* ```
|
|
766
905
|
*/
|
|
767
|
-
const frequencies = (
|
|
906
|
+
const frequencies = (items) => {
|
|
768
907
|
const resultMap = new globalThis.Map();
|
|
769
|
-
for (let i = 0; i <
|
|
770
|
-
const item =
|
|
908
|
+
for (let i = 0; i < items.length; i++) {
|
|
909
|
+
const item = items[i];
|
|
771
910
|
resultMap.set(item, (resultMap.get(item) ?? 0) + 1);
|
|
772
911
|
}
|
|
773
912
|
return resultMap;
|
|
774
913
|
};
|
|
775
914
|
/**
|
|
776
|
-
* Groups consecutive elements that share the same key returned by `
|
|
915
|
+
* Groups consecutive elements that share the same key returned by `keySelector`.
|
|
916
|
+
*
|
|
917
|
+
* @see {@link chunksOf} for fixed-size chunking.
|
|
777
918
|
*
|
|
778
919
|
* @example
|
|
779
920
|
* ```ts
|
|
@@ -783,14 +924,14 @@ const frequencies = (data) => {
|
|
|
783
924
|
* ); // [[1, 1], [2], [3, 3], [1]]
|
|
784
925
|
* ```
|
|
785
926
|
*/
|
|
786
|
-
const chunkBy = (
|
|
787
|
-
if (
|
|
927
|
+
const chunkBy = (keySelector) => (items) => {
|
|
928
|
+
if (items.length === 0) return [];
|
|
788
929
|
const result = [];
|
|
789
|
-
let currentChunk = [
|
|
790
|
-
let currentKey =
|
|
791
|
-
for (let i = 1; i <
|
|
792
|
-
const item =
|
|
793
|
-
const key =
|
|
930
|
+
let currentChunk = [items[0]];
|
|
931
|
+
let currentKey = keySelector(items[0]);
|
|
932
|
+
for (let i = 1; i < items.length; i++) {
|
|
933
|
+
const item = items[i];
|
|
934
|
+
const key = keySelector(item);
|
|
794
935
|
if (Object.is(key, currentKey)) currentChunk.push(item);
|
|
795
936
|
else {
|
|
796
937
|
result.push(currentChunk);
|
|
@@ -805,20 +946,22 @@ const chunkBy = (keyFn) => (data) => {
|
|
|
805
946
|
* Removes consecutive duplicate elements.
|
|
806
947
|
* An optional `Equality<A>` can be provided (defaults to `Object.is`).
|
|
807
948
|
*
|
|
949
|
+
* @see {@link uniq} for deduplicating across the entire array.
|
|
950
|
+
*
|
|
808
951
|
* @example
|
|
809
952
|
* ```ts
|
|
810
953
|
* Arr.dedupeAdjacent()([1, 1, 2, 2, 1, 3]); // [1, 2, 1, 3]
|
|
811
954
|
* ```
|
|
812
955
|
*/
|
|
813
|
-
const dedupeAdjacent = (
|
|
814
|
-
if (
|
|
815
|
-
const result = [
|
|
816
|
-
for (let i = 1; i <
|
|
956
|
+
const dedupeAdjacent = (areEqual = (first, second) => Object.is(first, second)) => (items) => {
|
|
957
|
+
if (items.length === 0) return [];
|
|
958
|
+
const result = [items[0]];
|
|
959
|
+
for (let i = 1; i < items.length; i++) if (!areEqual(items[i], result[result.length - 1])) result.push(items[i]);
|
|
817
960
|
return result;
|
|
818
961
|
};
|
|
819
962
|
/**
|
|
820
963
|
* Produces a sliding window of `size` elements over an array, advancing by `step` (default `1`).
|
|
821
|
-
* Returns an empty array if `size <= 0` or `size >
|
|
964
|
+
* Returns an empty array if `size <= 0` or `size > items.length`.
|
|
822
965
|
*
|
|
823
966
|
* @example
|
|
824
967
|
* ```ts
|
|
@@ -826,15 +969,15 @@ const dedupeAdjacent = (eq = (a, b) => Object.is(a, b)) => (data) => {
|
|
|
826
969
|
* pipe([1, 2, 3, 4], Arr.windowed(2, { step: 2 })); // [[1, 2], [3, 4]]
|
|
827
970
|
* ```
|
|
828
971
|
*/
|
|
829
|
-
const windowed = (windowSize, options) => (
|
|
972
|
+
const windowed = (windowSize, options) => (items) => {
|
|
830
973
|
const step = options?.step ?? 1;
|
|
831
|
-
if (windowSize <= 0 || step <= 0 ||
|
|
974
|
+
if (windowSize <= 0 || step <= 0 || items.length < windowSize) return [];
|
|
832
975
|
const result = [];
|
|
833
|
-
for (let i = 0; i <=
|
|
976
|
+
for (let i = 0; i <= items.length - windowSize; i += step) result.push(items.slice(i, i + windowSize));
|
|
834
977
|
return result;
|
|
835
978
|
};
|
|
836
979
|
/**
|
|
837
|
-
* Generates an array from an initial seed state until `
|
|
980
|
+
* Generates an array from an initial seed state until `step` returns `None`.
|
|
838
981
|
*
|
|
839
982
|
* @example
|
|
840
983
|
* ```ts
|
|
@@ -842,11 +985,11 @@ const windowed = (windowSize, options) => (data) => {
|
|
|
842
985
|
* // [1, 2, 3]
|
|
843
986
|
* ```
|
|
844
987
|
*/
|
|
845
|
-
const unfold = (initial,
|
|
988
|
+
const unfold = (initial, step) => {
|
|
846
989
|
const result = [];
|
|
847
990
|
let currentState = initial;
|
|
848
991
|
while (true) {
|
|
849
|
-
const next =
|
|
992
|
+
const next = step(currentState);
|
|
850
993
|
if (next.kind === "None") break;
|
|
851
994
|
const [item, nextState] = next.value;
|
|
852
995
|
result.push(item);
|
|
@@ -887,6 +1030,7 @@ const Arr = {
|
|
|
887
1030
|
prepend,
|
|
888
1031
|
append,
|
|
889
1032
|
size: size$3,
|
|
1033
|
+
length: size$3,
|
|
890
1034
|
some,
|
|
891
1035
|
every,
|
|
892
1036
|
reverse,
|
|
@@ -907,33 +1051,44 @@ const Arr = {
|
|
|
907
1051
|
dedupeAdjacent,
|
|
908
1052
|
windowed,
|
|
909
1053
|
unfold,
|
|
910
|
-
from: { Array: (data) => data.length > 0 ? require_Core.Maybe.make.some(data) : require_Core.Maybe.make.none() },
|
|
911
1054
|
is: {
|
|
912
|
-
|
|
913
|
-
|
|
1055
|
+
/**
|
|
1056
|
+
* Returns `true` when the array is empty.
|
|
1057
|
+
*
|
|
1058
|
+
* @see {@link nonEmpty} for checking if an array contains elements.
|
|
1059
|
+
*/
|
|
1060
|
+
empty: (items) => items.length === 0,
|
|
1061
|
+
/**
|
|
1062
|
+
* Returns `true` when the array contains at least one element.
|
|
1063
|
+
*
|
|
1064
|
+
* @see {@link empty} for checking if an array is empty.
|
|
1065
|
+
*/
|
|
1066
|
+
nonEmpty: (items) => require_Core.isNonEmptyArr(items)
|
|
914
1067
|
},
|
|
915
1068
|
traverse: {
|
|
916
1069
|
Maybe: ArrMaybe.traverse,
|
|
917
1070
|
Result: ArrResult.traverse,
|
|
918
|
-
Task: _traverseTask
|
|
1071
|
+
Task: _traverseTask,
|
|
1072
|
+
Validation: ArrValidation.traverse
|
|
919
1073
|
},
|
|
920
1074
|
sequence: {
|
|
921
1075
|
Maybe: ArrMaybe.sequence,
|
|
922
1076
|
Result: ArrResult.sequence,
|
|
923
|
-
Task: _sequenceTask
|
|
1077
|
+
Task: _sequenceTask,
|
|
1078
|
+
Validation: ArrValidation.sequence
|
|
924
1079
|
},
|
|
925
1080
|
NonEmpty: {
|
|
926
|
-
singleton: (
|
|
927
|
-
from: {
|
|
928
|
-
head: (
|
|
929
|
-
last: (
|
|
930
|
-
tail: (
|
|
931
|
-
reduce: (
|
|
932
|
-
map: (
|
|
933
|
-
mapWithIndex: (
|
|
934
|
-
intersperse: (
|
|
935
|
-
concat: (other) => (
|
|
936
|
-
reverse: (
|
|
1081
|
+
singleton: (item) => [item],
|
|
1082
|
+
from: { array: (items) => require_Core.isNonEmptyArr(items) ? require_Core.Maybe.make.some(items) : require_Core.Maybe.make.none() },
|
|
1083
|
+
head: (items) => items[0],
|
|
1084
|
+
last: (items) => items[items.length - 1],
|
|
1085
|
+
tail: (items) => items.slice(1),
|
|
1086
|
+
reduce: (reducer) => (items) => items.reduce(reducer),
|
|
1087
|
+
map: (transform) => (items) => map$3(transform)(items),
|
|
1088
|
+
mapWithIndex: (transform) => (items) => mapWithIndex(transform)(items),
|
|
1089
|
+
intersperse: (separator) => (items) => intersperse(separator)(items),
|
|
1090
|
+
concat: (other) => (items) => concat(other)(items),
|
|
1091
|
+
reverse: (items) => reverse(items)
|
|
937
1092
|
}
|
|
938
1093
|
};
|
|
939
1094
|
//#endregion
|
|
@@ -964,30 +1119,36 @@ const BigNum = {
|
|
|
964
1119
|
* BigNum.is.zero(5n); // false
|
|
965
1120
|
* ```
|
|
966
1121
|
*/
|
|
967
|
-
zero: (
|
|
1122
|
+
zero: (value) => value === 0n,
|
|
968
1123
|
/**
|
|
969
1124
|
* Returns `true` when the bigint is an even integer.
|
|
970
1125
|
*
|
|
1126
|
+
* @see {@link BigNum.is.odd} to check if a bigint is odd.
|
|
1127
|
+
*
|
|
971
1128
|
* @example
|
|
972
1129
|
* ```ts
|
|
973
1130
|
* BigNum.is.even(4n); // true
|
|
974
1131
|
* BigNum.is.even(3n); // false
|
|
975
1132
|
* ```
|
|
976
1133
|
*/
|
|
977
|
-
even: (
|
|
1134
|
+
even: (value) => value % 2n === 0n,
|
|
978
1135
|
/**
|
|
979
1136
|
* Returns `true` when the bigint is an odd integer.
|
|
980
1137
|
*
|
|
1138
|
+
* @see {@link BigNum.is.even} to check if a bigint is even.
|
|
1139
|
+
*
|
|
981
1140
|
* @example
|
|
982
1141
|
* ```ts
|
|
983
1142
|
* BigNum.is.odd(3n); // true
|
|
984
1143
|
* BigNum.is.odd(4n); // false
|
|
985
1144
|
* ```
|
|
986
1145
|
*/
|
|
987
|
-
odd: (
|
|
1146
|
+
odd: (value) => value % 2n !== 0n,
|
|
988
1147
|
/**
|
|
989
1148
|
* Returns `true` when the bigint is strictly greater than zero (`0n`).
|
|
990
1149
|
*
|
|
1150
|
+
* @see {@link BigNum.is.negative} to check if a bigint is less than zero.
|
|
1151
|
+
*
|
|
991
1152
|
* @example
|
|
992
1153
|
* ```ts
|
|
993
1154
|
* BigNum.is.positive(5n); // true
|
|
@@ -995,10 +1156,12 @@ const BigNum = {
|
|
|
995
1156
|
* BigNum.is.positive(-5n); // false
|
|
996
1157
|
* ```
|
|
997
1158
|
*/
|
|
998
|
-
positive: (
|
|
1159
|
+
positive: (value) => value > 0n,
|
|
999
1160
|
/**
|
|
1000
1161
|
* Returns `true` when the bigint is strictly less than zero (`0n`).
|
|
1001
1162
|
*
|
|
1163
|
+
* @see {@link BigNum.is.positive} to check if a bigint is greater than zero.
|
|
1164
|
+
*
|
|
1002
1165
|
* @example
|
|
1003
1166
|
* ```ts
|
|
1004
1167
|
* BigNum.is.negative(-5n); // true
|
|
@@ -1006,7 +1169,7 @@ const BigNum = {
|
|
|
1006
1169
|
* BigNum.is.negative(5n); // false
|
|
1007
1170
|
* ```
|
|
1008
1171
|
*/
|
|
1009
|
-
negative: (
|
|
1172
|
+
negative: (value) => value < 0n
|
|
1010
1173
|
},
|
|
1011
1174
|
from: {
|
|
1012
1175
|
/**
|
|
@@ -1018,10 +1181,10 @@ const BigNum = {
|
|
|
1018
1181
|
* BigNum.from.string("abc"); // None
|
|
1019
1182
|
* ```
|
|
1020
1183
|
*/
|
|
1021
|
-
string: (
|
|
1184
|
+
string: (text) => {
|
|
1022
1185
|
try {
|
|
1023
|
-
if (
|
|
1024
|
-
return require_Core.Maybe.make.some(BigInt(
|
|
1186
|
+
if (text.trim() === "") return require_Core.Maybe.make.none();
|
|
1187
|
+
return require_Core.Maybe.make.some(BigInt(text));
|
|
1025
1188
|
} catch {
|
|
1026
1189
|
return require_Core.Maybe.make.none();
|
|
1027
1190
|
}
|
|
@@ -1035,9 +1198,9 @@ const BigNum = {
|
|
|
1035
1198
|
* BigNum.from.number(3.14); // None
|
|
1036
1199
|
* ```
|
|
1037
1200
|
*/
|
|
1038
|
-
number: (
|
|
1039
|
-
if (!Number.isInteger(
|
|
1040
|
-
return require_Core.Maybe.make.some(BigInt(
|
|
1201
|
+
number: (value) => {
|
|
1202
|
+
if (!Number.isInteger(value) || value < Number.MIN_SAFE_INTEGER || value > Number.MAX_SAFE_INTEGER) return require_Core.Maybe.make.none();
|
|
1203
|
+
return require_Core.Maybe.make.some(BigInt(value));
|
|
1041
1204
|
}
|
|
1042
1205
|
},
|
|
1043
1206
|
to: {
|
|
@@ -1050,75 +1213,100 @@ const BigNum = {
|
|
|
1050
1213
|
* BigNum.to.number(9007199254740993n); // None
|
|
1051
1214
|
* ```
|
|
1052
1215
|
*/
|
|
1053
|
-
number: (
|
|
1054
|
-
if (
|
|
1055
|
-
return require_Core.Maybe.make.some(Number(
|
|
1216
|
+
number: (value) => {
|
|
1217
|
+
if (value < BigInt(Number.MIN_SAFE_INTEGER) || value > BigInt(Number.MAX_SAFE_INTEGER)) return require_Core.Maybe.make.none();
|
|
1218
|
+
return require_Core.Maybe.make.some(Number(value));
|
|
1056
1219
|
} },
|
|
1057
1220
|
/**
|
|
1058
|
-
* Adds `
|
|
1221
|
+
* Adds `amount` to `value`. Data-last curried signature: `add(amount)(value)` = `value + amount`.
|
|
1222
|
+
*
|
|
1223
|
+
* @see {@link BigNum.subtract} to subtract an amount from a bigint.
|
|
1059
1224
|
*
|
|
1060
1225
|
* @example
|
|
1061
1226
|
* ```ts
|
|
1062
1227
|
* pipe(10n, BigNum.add(5n)); // 15n
|
|
1063
1228
|
* ```
|
|
1064
1229
|
*/
|
|
1065
|
-
add: (
|
|
1230
|
+
add: (amount) => (value) => value + amount,
|
|
1066
1231
|
/**
|
|
1067
|
-
* Subtracts `
|
|
1232
|
+
* Subtracts `amount` from `from`. Data-last curried signature: `subtract(amount)(from)` = `from - amount`.
|
|
1233
|
+
*
|
|
1234
|
+
* @see {@link BigNum.add} to add an amount to a bigint.
|
|
1068
1235
|
*
|
|
1069
1236
|
* @example
|
|
1070
1237
|
* ```ts
|
|
1071
|
-
* pipe(10n, BigNum.
|
|
1238
|
+
* pipe(10n, BigNum.subtract(3n)); // 7n
|
|
1072
1239
|
* ```
|
|
1073
1240
|
*/
|
|
1074
|
-
|
|
1241
|
+
subtract: (amount) => (from) => from - amount,
|
|
1075
1242
|
/**
|
|
1076
|
-
* Multiplies `
|
|
1243
|
+
* Multiplies `value` by `factor`. Data-last curried signature: `multiply(factor)(value)` = `value * factor`.
|
|
1244
|
+
*
|
|
1245
|
+
* @see {@link BigNum.divide} to divide a bigint by a divisor.
|
|
1077
1246
|
*
|
|
1078
1247
|
* @example
|
|
1079
1248
|
* ```ts
|
|
1080
|
-
* pipe(6n, BigNum.
|
|
1249
|
+
* pipe(6n, BigNum.multiply(7n)); // 42n
|
|
1081
1250
|
* ```
|
|
1082
1251
|
*/
|
|
1083
|
-
|
|
1252
|
+
multiply: (factor) => (value) => value * factor,
|
|
1084
1253
|
/**
|
|
1085
|
-
* Divides `
|
|
1254
|
+
* Divides `dividend` by `divisor`. Returns `None` if `divisor` is `0n`.
|
|
1255
|
+
*
|
|
1256
|
+
* @see {@link BigNum.multiply} to multiply a bigint by a factor.
|
|
1257
|
+
* @see {@link BigNum.remainder} to compute the division remainder.
|
|
1086
1258
|
*
|
|
1087
1259
|
* @example
|
|
1088
1260
|
* ```ts
|
|
1089
|
-
* pipe(20n, BigNum.
|
|
1090
|
-
* pipe(5n, BigNum.
|
|
1261
|
+
* pipe(20n, BigNum.divide(4n)); // Some(5n)
|
|
1262
|
+
* pipe(5n, BigNum.divide(0n)); // None
|
|
1091
1263
|
* ```
|
|
1092
1264
|
*/
|
|
1093
|
-
|
|
1265
|
+
divide: (divisor) => (dividend) => divisor === 0n ? require_Core.Maybe.make.none() : require_Core.Maybe.make.some(dividend / divisor),
|
|
1094
1266
|
/**
|
|
1095
|
-
* Computes remainder of `
|
|
1267
|
+
* Computes remainder of `dividend / divisor`. Returns `None` if `divisor` is `0n`.
|
|
1268
|
+
*
|
|
1269
|
+
* @see {@link BigNum.divide} for full division.
|
|
1096
1270
|
*
|
|
1097
1271
|
* @example
|
|
1098
1272
|
* ```ts
|
|
1099
|
-
* pipe(10n, BigNum.
|
|
1100
|
-
* pipe(5n, BigNum.
|
|
1273
|
+
* pipe(10n, BigNum.remainder(3n)); // Some(1n)
|
|
1274
|
+
* pipe(5n, BigNum.remainder(0n)); // None
|
|
1101
1275
|
* ```
|
|
1102
1276
|
*/
|
|
1103
|
-
|
|
1277
|
+
remainder: (divisor) => (dividend) => divisor === 0n ? require_Core.Maybe.make.none() : require_Core.Maybe.make.some(dividend % divisor),
|
|
1104
1278
|
/**
|
|
1105
|
-
* Clamps `
|
|
1279
|
+
* Clamps `value` between `min` and `max` (inclusive).
|
|
1106
1280
|
*
|
|
1107
1281
|
* @example
|
|
1108
1282
|
* ```ts
|
|
1109
1283
|
* pipe(150n, BigNum.clamp(0n, 100n)); // 100n
|
|
1110
1284
|
* ```
|
|
1111
1285
|
*/
|
|
1112
|
-
clamp: (min, max) => (
|
|
1286
|
+
clamp: (min, max) => (value) => value < min ? min : value > max ? max : value,
|
|
1287
|
+
/**
|
|
1288
|
+
* Returns `true` when the bigint is between `min` and `max` (both inclusive).
|
|
1289
|
+
*
|
|
1290
|
+
* @see {@link BigNum.inRange} for half-open range checking [start, end).
|
|
1291
|
+
*
|
|
1292
|
+
* @example
|
|
1293
|
+
* ```ts
|
|
1294
|
+
* pipe(5n, BigNum.between(1n, 10n)); // true
|
|
1295
|
+
* pipe(0n, BigNum.between(1n, 10n)); // false
|
|
1296
|
+
* ```
|
|
1297
|
+
*/
|
|
1298
|
+
between: (min, max) => (value) => value >= min && value <= max,
|
|
1113
1299
|
/**
|
|
1114
|
-
* Returns `true` if `
|
|
1300
|
+
* Returns `true` if `value` is in the range `[start, end)` (inclusive start, exclusive end).
|
|
1301
|
+
*
|
|
1302
|
+
* @see {@link BigNum.between} for fully closed range checking [min, max].
|
|
1115
1303
|
*
|
|
1116
1304
|
* @example
|
|
1117
1305
|
* ```ts
|
|
1118
1306
|
* pipe(5n, BigNum.inRange(1n, 10n)); // true
|
|
1119
1307
|
* ```
|
|
1120
1308
|
*/
|
|
1121
|
-
inRange: (start, end) => (
|
|
1309
|
+
inRange: (start, end) => (value) => value >= start && value < end,
|
|
1122
1310
|
/**
|
|
1123
1311
|
* Returns absolute value of a `bigint`.
|
|
1124
1312
|
*
|
|
@@ -1127,65 +1315,69 @@ number: (b) => {
|
|
|
1127
1315
|
* BigNum.abs(-42n); // 42n
|
|
1128
1316
|
* ```
|
|
1129
1317
|
*/
|
|
1130
|
-
abs: (
|
|
1318
|
+
abs: (value) => value < 0n ? -value : value,
|
|
1131
1319
|
/**
|
|
1132
|
-
* Returns the minimum of `
|
|
1320
|
+
* Returns the minimum of `value` and `other`.
|
|
1321
|
+
*
|
|
1322
|
+
* @see {@link BigNum.max} to determine the maximum value.
|
|
1133
1323
|
*
|
|
1134
1324
|
* @example
|
|
1135
1325
|
* ```ts
|
|
1136
1326
|
* pipe(10n, BigNum.min(5n)); // 5n
|
|
1137
1327
|
* ```
|
|
1138
1328
|
*/
|
|
1139
|
-
min: (
|
|
1329
|
+
min: (other) => (value) => value < other ? value : other,
|
|
1140
1330
|
/**
|
|
1141
|
-
* Returns the maximum of `
|
|
1331
|
+
* Returns the maximum of `value` and `other`.
|
|
1332
|
+
*
|
|
1333
|
+
* @see {@link BigNum.min} to determine the minimum value.
|
|
1142
1334
|
*
|
|
1143
1335
|
* @example
|
|
1144
1336
|
* ```ts
|
|
1145
1337
|
* pipe(10n, BigNum.max(5n)); // 10n
|
|
1146
1338
|
* ```
|
|
1147
1339
|
*/
|
|
1148
|
-
max: (
|
|
1340
|
+
max: (other) => (value) => value > other ? value : other
|
|
1149
1341
|
};
|
|
1150
1342
|
//#endregion
|
|
1151
1343
|
//#region src/Data/Bool.ts
|
|
1152
|
-
const isBoolean = (
|
|
1153
|
-
const isTrue = (
|
|
1154
|
-
const isFalse = (
|
|
1155
|
-
const isTruthy = (
|
|
1156
|
-
const isFalsy = (
|
|
1157
|
-
const not = (
|
|
1158
|
-
const and = (that) => (
|
|
1159
|
-
const or = (that) => (
|
|
1160
|
-
const xor = (that) => (
|
|
1161
|
-
const andLazy = (that) => (
|
|
1162
|
-
const orLazy = (that) => (
|
|
1163
|
-
const all = (
|
|
1164
|
-
for (let i = 0; i <
|
|
1344
|
+
const isBoolean = (value) => typeof value === "boolean";
|
|
1345
|
+
const isTrue = (value) => value === true;
|
|
1346
|
+
const isFalse = (value) => value === false;
|
|
1347
|
+
const isTruthy = (value) => Boolean(value);
|
|
1348
|
+
const isFalsy = (value) => !value;
|
|
1349
|
+
const not = (condition) => !condition;
|
|
1350
|
+
const and = (that) => (condition) => condition && that;
|
|
1351
|
+
const or = (that) => (condition) => condition || that;
|
|
1352
|
+
const xor = (that) => (condition) => condition !== that;
|
|
1353
|
+
const andLazy = (that) => (condition) => condition && that();
|
|
1354
|
+
const orLazy = (that) => (condition) => condition || that();
|
|
1355
|
+
const all = (conditions) => {
|
|
1356
|
+
for (let i = 0; i < conditions.length; i++) if (!conditions[i]) return false;
|
|
1165
1357
|
return true;
|
|
1166
1358
|
};
|
|
1167
|
-
const any = (
|
|
1168
|
-
for (let i = 0; i <
|
|
1359
|
+
const any = (conditions) => {
|
|
1360
|
+
for (let i = 0; i < conditions.length; i++) if (conditions[i]) return true;
|
|
1169
1361
|
return false;
|
|
1170
1362
|
};
|
|
1171
|
-
const fold = (onFalse, onTrue) => (
|
|
1172
|
-
const match = (cases) => (
|
|
1173
|
-
const fromString = (
|
|
1174
|
-
const trimmed =
|
|
1363
|
+
const fold = (onFalse, onTrue) => (condition) => condition ? onTrue() : onFalse();
|
|
1364
|
+
const match = (cases) => (condition) => condition ? cases.true() : cases.false();
|
|
1365
|
+
const fromString = (text) => {
|
|
1366
|
+
const trimmed = text.trim().toLowerCase();
|
|
1175
1367
|
if (trimmed === "true") return require_Core.Maybe.make.some(true);
|
|
1176
1368
|
if (trimmed === "false") return require_Core.Maybe.make.some(false);
|
|
1177
1369
|
return require_Core.Maybe.make.none();
|
|
1178
1370
|
};
|
|
1179
|
-
const fromNumber = (
|
|
1180
|
-
if (
|
|
1181
|
-
if (
|
|
1371
|
+
const fromNumber = (value) => {
|
|
1372
|
+
if (value === 1) return require_Core.Maybe.make.some(true);
|
|
1373
|
+
if (value === 0) return require_Core.Maybe.make.some(false);
|
|
1182
1374
|
return require_Core.Maybe.make.none();
|
|
1183
1375
|
};
|
|
1184
1376
|
const fromTruthy = (value) => Boolean(value);
|
|
1185
|
-
const toMaybe = (onTrue) => (
|
|
1186
|
-
const toResult = (onErr, onOk) => (
|
|
1187
|
-
const toNumber = (
|
|
1188
|
-
const toString = (
|
|
1377
|
+
const toMaybe = (onTrue) => (condition) => condition ? require_Core.Maybe.make.some(onTrue()) : require_Core.Maybe.make.none();
|
|
1378
|
+
const toResult = (onErr, onOk) => (condition) => condition ? require_Core.Result.make.ok(onOk()) : require_Core.Result.make.err(onErr());
|
|
1379
|
+
const toNumber = (condition) => condition ? 1 : 0;
|
|
1380
|
+
const toString = (condition) => condition ? "true" : "false";
|
|
1189
1381
|
const Bool = {
|
|
1190
1382
|
is: {
|
|
1191
1383
|
/**
|
|
@@ -1203,6 +1395,8 @@ const Bool = {
|
|
|
1203
1395
|
/**
|
|
1204
1396
|
* Narrowing guard — checks if a value is strictly `true`.
|
|
1205
1397
|
*
|
|
1398
|
+
* @see {@link Bool.is.false} to check if a value is strictly false.
|
|
1399
|
+
*
|
|
1206
1400
|
* @example
|
|
1207
1401
|
* ```ts
|
|
1208
1402
|
* Bool.is.true(true); // true
|
|
@@ -1213,6 +1407,8 @@ const Bool = {
|
|
|
1213
1407
|
/**
|
|
1214
1408
|
* Narrowing guard — checks if a value is strictly `false`.
|
|
1215
1409
|
*
|
|
1410
|
+
* @see {@link Bool.is.true} to check if a value is strictly true.
|
|
1411
|
+
*
|
|
1216
1412
|
* @example
|
|
1217
1413
|
* ```ts
|
|
1218
1414
|
* Bool.is.false(false); // true
|
|
@@ -1223,6 +1419,8 @@ const Bool = {
|
|
|
1223
1419
|
/**
|
|
1224
1420
|
* Type guard — checks if a value is truthy (not `false`, `0`, `0n`, `""`, `null`, `undefined`, or `NaN`).
|
|
1225
1421
|
*
|
|
1422
|
+
* @see {@link Bool.is.falsy} to check if a value is falsy.
|
|
1423
|
+
*
|
|
1226
1424
|
* @example
|
|
1227
1425
|
* ```ts
|
|
1228
1426
|
* Bool.is.truthy("hello"); // true
|
|
@@ -1235,6 +1433,8 @@ const Bool = {
|
|
|
1235
1433
|
/**
|
|
1236
1434
|
* Type guard — checks if a value is falsy (`false`, `0`, `0n`, `""`, `null`, `undefined`, or `NaN`).
|
|
1237
1435
|
*
|
|
1436
|
+
* @see {@link Bool.is.truthy} to check if a value is truthy.
|
|
1437
|
+
*
|
|
1238
1438
|
* @example
|
|
1239
1439
|
* ```ts
|
|
1240
1440
|
* Bool.is.falsy(""); // true
|
|
@@ -1255,9 +1455,12 @@ const Bool = {
|
|
|
1255
1455
|
*/
|
|
1256
1456
|
not,
|
|
1257
1457
|
/**
|
|
1258
|
-
* Logical AND combinator. Returns `true` only if both `
|
|
1458
|
+
* Logical AND combinator. Returns `true` only if both `condition` and `that` are `true`.
|
|
1259
1459
|
*
|
|
1260
|
-
* Data-last: `pipe(
|
|
1460
|
+
* Data-last: `pipe(condition, Bool.and(that))`.
|
|
1461
|
+
*
|
|
1462
|
+
* @see {@link Bool.or} for logical OR combinator.
|
|
1463
|
+
* @see {@link Bool.andLazy} for short-circuiting lazy evaluation.
|
|
1261
1464
|
*
|
|
1262
1465
|
* @example
|
|
1263
1466
|
* ```ts
|
|
@@ -1267,9 +1470,12 @@ const Bool = {
|
|
|
1267
1470
|
*/
|
|
1268
1471
|
and,
|
|
1269
1472
|
/**
|
|
1270
|
-
* Logical OR combinator. Returns `true` if either `
|
|
1473
|
+
* Logical OR combinator. Returns `true` if either `condition` or `that` is `true`.
|
|
1474
|
+
*
|
|
1475
|
+
* Data-last: `pipe(condition, Bool.or(that))`.
|
|
1271
1476
|
*
|
|
1272
|
-
*
|
|
1477
|
+
* @see {@link Bool.and} for logical AND combinator.
|
|
1478
|
+
* @see {@link Bool.orLazy} for short-circuiting lazy evaluation.
|
|
1273
1479
|
*
|
|
1274
1480
|
* @example
|
|
1275
1481
|
* ```ts
|
|
@@ -1279,9 +1485,9 @@ const Bool = {
|
|
|
1279
1485
|
*/
|
|
1280
1486
|
or,
|
|
1281
1487
|
/**
|
|
1282
|
-
* Logical XOR (exclusive OR) combinator. Returns `true` if exactly one of `
|
|
1488
|
+
* Logical XOR (exclusive OR) combinator. Returns `true` if exactly one of `condition` and `that` is `true`.
|
|
1283
1489
|
*
|
|
1284
|
-
* Data-last: `pipe(
|
|
1490
|
+
* Data-last: `pipe(condition, Bool.xor(that))`.
|
|
1285
1491
|
*
|
|
1286
1492
|
* @example
|
|
1287
1493
|
* ```ts
|
|
@@ -1292,9 +1498,12 @@ const Bool = {
|
|
|
1292
1498
|
xor,
|
|
1293
1499
|
/**
|
|
1294
1500
|
* Lazy logical AND combinator.
|
|
1295
|
-
* If `
|
|
1501
|
+
* If `condition` is `false`, the `that` computation is never evaluated.
|
|
1296
1502
|
*
|
|
1297
|
-
* Data-last: `pipe(
|
|
1503
|
+
* Data-last: `pipe(condition, Bool.andLazy(that))`.
|
|
1504
|
+
*
|
|
1505
|
+
* @see {@link Bool.orLazy} for lazy logical OR combinator.
|
|
1506
|
+
* @see {@link Bool.and} for strict logical AND evaluation.
|
|
1298
1507
|
*
|
|
1299
1508
|
* @example
|
|
1300
1509
|
* ```ts
|
|
@@ -1307,9 +1516,12 @@ const Bool = {
|
|
|
1307
1516
|
andLazy,
|
|
1308
1517
|
/**
|
|
1309
1518
|
* Lazy logical OR combinator.
|
|
1310
|
-
* If `
|
|
1519
|
+
* If `condition` is `true`, the `that` computation is never evaluated.
|
|
1520
|
+
*
|
|
1521
|
+
* Data-last: `pipe(condition, Bool.orLazy(that))`.
|
|
1311
1522
|
*
|
|
1312
|
-
*
|
|
1523
|
+
* @see {@link Bool.andLazy} for lazy logical AND combinator.
|
|
1524
|
+
* @see {@link Bool.or} for strict logical OR evaluation.
|
|
1313
1525
|
*
|
|
1314
1526
|
* @example
|
|
1315
1527
|
* ```ts
|
|
@@ -1325,6 +1537,8 @@ const Bool = {
|
|
|
1325
1537
|
* Returns `true` if every boolean is `true`, or for an empty array (vacuous truth).
|
|
1326
1538
|
* Short-circuits on the first `false`.
|
|
1327
1539
|
*
|
|
1540
|
+
* @see {@link Bool.any} to check if at least one boolean is true.
|
|
1541
|
+
*
|
|
1328
1542
|
* @example
|
|
1329
1543
|
* ```ts
|
|
1330
1544
|
* Bool.all([true, true, true]); // true
|
|
@@ -1338,6 +1552,8 @@ const Bool = {
|
|
|
1338
1552
|
* Returns `true` if at least one boolean is `true`. Returns `false` for an empty array.
|
|
1339
1553
|
* Short-circuits on the first `true`.
|
|
1340
1554
|
*
|
|
1555
|
+
* @see {@link Bool.all} to check if all booleans are true.
|
|
1556
|
+
*
|
|
1341
1557
|
* @example
|
|
1342
1558
|
* ```ts
|
|
1343
1559
|
* Bool.any([false, true, false]); // true
|
|
@@ -1352,6 +1568,8 @@ const Bool = {
|
|
|
1352
1568
|
* Positional ordering: `onFalse` first, `onTrue` second.
|
|
1353
1569
|
* Aligned with `Result.fold(onErr, onOk)` and `Maybe.fold(onNone, onSome)`.
|
|
1354
1570
|
*
|
|
1571
|
+
* @see {@link Bool.match} for named-case pattern matching with an object literal.
|
|
1572
|
+
*
|
|
1355
1573
|
* @example
|
|
1356
1574
|
* ```ts
|
|
1357
1575
|
* pipe(
|
|
@@ -1367,6 +1585,8 @@ const Bool = {
|
|
|
1367
1585
|
/**
|
|
1368
1586
|
* Pattern matching on boolean using named cases `{ true, false }`.
|
|
1369
1587
|
*
|
|
1588
|
+
* @see {@link Bool.fold} for positional argument pattern matching.
|
|
1589
|
+
*
|
|
1370
1590
|
* @example
|
|
1371
1591
|
* ```ts
|
|
1372
1592
|
* pipe(
|
|
@@ -1471,119 +1691,221 @@ const Bool = {
|
|
|
1471
1691
|
//#endregion
|
|
1472
1692
|
//#region src/Data/Dict.ts
|
|
1473
1693
|
const DictIs = {
|
|
1474
|
-
|
|
1475
|
-
|
|
1694
|
+
/**
|
|
1695
|
+
* Returns `true` when the dictionary contains zero entries.
|
|
1696
|
+
*
|
|
1697
|
+
* @see {@link nonEmpty} for checking if a dictionary contains entries.
|
|
1698
|
+
*/
|
|
1699
|
+
empty: (dict) => dict.size === 0,
|
|
1700
|
+
/**
|
|
1701
|
+
* Returns `true` when the dictionary contains at least one entry.
|
|
1702
|
+
*
|
|
1703
|
+
* @see {@link empty} for checking if a dictionary is empty.
|
|
1704
|
+
*/
|
|
1705
|
+
nonEmpty: (dict) => dict.size > 0
|
|
1476
1706
|
};
|
|
1477
1707
|
const empty$1 = () => new globalThis.Map();
|
|
1478
1708
|
const singleton$1 = (key, value) => new globalThis.Map([[key, value]]);
|
|
1479
1709
|
const DictFrom = {
|
|
1480
1710
|
entries: (entries) => new globalThis.Map(entries),
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
nullable: (data) => data === null || data === void 0 ? require_Core.Maybe.make.none() : require_Core.Maybe.make.some(data)
|
|
1711
|
+
record: (record) => new globalThis.Map(Object.entries(record)),
|
|
1712
|
+
nullable: (dict) => dict === null || dict === void 0 ? require_Core.Maybe.make.none() : require_Core.Maybe.make.some(dict)
|
|
1484
1713
|
};
|
|
1485
|
-
const DictTo = {
|
|
1714
|
+
const DictTo = { record: (dict) => {
|
|
1486
1715
|
const result = {};
|
|
1487
|
-
for (const [k, v] of
|
|
1716
|
+
for (const [k, v] of dict) result[k] = v;
|
|
1488
1717
|
return result;
|
|
1489
1718
|
} };
|
|
1490
|
-
const groupBy$1 = (
|
|
1719
|
+
const groupBy$1 = (keySelector) => (items) => {
|
|
1491
1720
|
const result = new globalThis.Map();
|
|
1492
|
-
for (const
|
|
1493
|
-
const k =
|
|
1721
|
+
for (const item of items) {
|
|
1722
|
+
const k = keySelector(item);
|
|
1494
1723
|
const existing = result.get(k);
|
|
1495
|
-
if (existing !== void 0) existing.push(
|
|
1496
|
-
else result.set(k, [
|
|
1724
|
+
if (existing !== void 0) existing.push(item);
|
|
1725
|
+
else result.set(k, [item]);
|
|
1497
1726
|
}
|
|
1498
1727
|
return result;
|
|
1499
1728
|
};
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
const
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1729
|
+
/**
|
|
1730
|
+
* Returns `true` when the dictionary contains the specified key.
|
|
1731
|
+
*
|
|
1732
|
+
* @see {@link lookup} for retrieving the value associated with a key.
|
|
1733
|
+
*/
|
|
1734
|
+
const has$1 = (key) => (dict) => dict.has(key);
|
|
1735
|
+
/**
|
|
1736
|
+
* Retrieves the value associated with a key wrapped in a `Maybe`.
|
|
1737
|
+
*
|
|
1738
|
+
* @see {@link has} for checking key existence without retrieving the value.
|
|
1739
|
+
*/
|
|
1740
|
+
const lookup$1 = (key) => (dict) => {
|
|
1741
|
+
const val = dict.get(key);
|
|
1742
|
+
return val !== void 0 || dict.has(key) ? require_Core.Maybe.make.some(val) : require_Core.Maybe.make.none();
|
|
1743
|
+
};
|
|
1744
|
+
const size$2 = (dict) => dict.size;
|
|
1745
|
+
/**
|
|
1746
|
+
* Returns all keys of a dictionary.
|
|
1747
|
+
*
|
|
1748
|
+
* @see {@link values} for extracting dictionary values.
|
|
1749
|
+
* @see {@link entries} for extracting key-value pairs.
|
|
1750
|
+
*/
|
|
1751
|
+
const keys$1 = (dict) => Array.from(dict.keys());
|
|
1752
|
+
/**
|
|
1753
|
+
* Returns all values of a dictionary.
|
|
1754
|
+
*
|
|
1755
|
+
* @see {@link keys} for extracting dictionary keys.
|
|
1756
|
+
* @see {@link entries} for extracting key-value pairs.
|
|
1757
|
+
*/
|
|
1758
|
+
const values$1 = (dict) => Array.from(dict.values());
|
|
1759
|
+
/**
|
|
1760
|
+
* Returns all key-value pairs of a dictionary.
|
|
1761
|
+
*
|
|
1762
|
+
* @see {@link keys} for extracting dictionary keys.
|
|
1763
|
+
* @see {@link values} for extracting dictionary values.
|
|
1764
|
+
*/
|
|
1765
|
+
const entries$1 = (dict) => Array.from(dict.entries());
|
|
1766
|
+
/**
|
|
1767
|
+
* Returns a new dictionary with the key set to value.
|
|
1768
|
+
*
|
|
1769
|
+
* @see {@link remove} for deleting a key from a dictionary.
|
|
1770
|
+
* @see {@link upsert} for conditional insertion/update.
|
|
1771
|
+
*/
|
|
1772
|
+
const insert = (key, value) => (dict) => {
|
|
1773
|
+
const res = new globalThis.Map(dict);
|
|
1511
1774
|
res.set(key, value);
|
|
1512
1775
|
return res;
|
|
1513
1776
|
};
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1777
|
+
/**
|
|
1778
|
+
* Returns a new dictionary with the specified key removed.
|
|
1779
|
+
*
|
|
1780
|
+
* @see {@link insert} for adding or replacing a key in a dictionary.
|
|
1781
|
+
*/
|
|
1782
|
+
const remove$1 = (key) => (dict) => {
|
|
1783
|
+
if (!dict.has(key)) return dict;
|
|
1784
|
+
const res = new globalThis.Map(dict);
|
|
1517
1785
|
res.delete(key);
|
|
1518
1786
|
return res;
|
|
1519
1787
|
};
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1788
|
+
/**
|
|
1789
|
+
* Inserts or updates a key using a callback that receives the existing value if present.
|
|
1790
|
+
*
|
|
1791
|
+
* @see {@link insert} for unconditional key setting.
|
|
1792
|
+
*/
|
|
1793
|
+
const upsert = (key, update) => (dict) => {
|
|
1794
|
+
const res = new globalThis.Map(dict);
|
|
1795
|
+
const existing = dict.has(key) ? require_Core.Maybe.make.some(dict.get(key)) : require_Core.Maybe.make.none();
|
|
1796
|
+
res.set(key, update(existing));
|
|
1524
1797
|
return res;
|
|
1525
1798
|
};
|
|
1526
|
-
|
|
1799
|
+
/**
|
|
1800
|
+
* Transforms each value in the dictionary.
|
|
1801
|
+
*
|
|
1802
|
+
* @see {@link mapWithKey} for transforming values with key access.
|
|
1803
|
+
*/
|
|
1804
|
+
const map$2 = (transform) => (dict) => {
|
|
1527
1805
|
const res = new globalThis.Map();
|
|
1528
|
-
for (const [k, v] of
|
|
1806
|
+
for (const [k, v] of dict) res.set(k, transform(v));
|
|
1529
1807
|
return res;
|
|
1530
1808
|
};
|
|
1531
|
-
|
|
1809
|
+
/**
|
|
1810
|
+
* Transforms each value in the dictionary, also receiving the key.
|
|
1811
|
+
*
|
|
1812
|
+
* @see {@link map} for transforming values without key access.
|
|
1813
|
+
*/
|
|
1814
|
+
const mapWithKey$1 = (transform) => (dict) => {
|
|
1532
1815
|
const res = new globalThis.Map();
|
|
1533
|
-
for (const [k, v] of
|
|
1816
|
+
for (const [k, v] of dict) res.set(k, transform(k, v));
|
|
1534
1817
|
return res;
|
|
1535
1818
|
};
|
|
1536
|
-
|
|
1819
|
+
/**
|
|
1820
|
+
* Filters dictionary entries by a predicate on values.
|
|
1821
|
+
*
|
|
1822
|
+
* @see {@link filterWithKey} for filtering with key access.
|
|
1823
|
+
*/
|
|
1824
|
+
const filter$2 = (predicate) => (dict) => {
|
|
1537
1825
|
const res = new globalThis.Map();
|
|
1538
|
-
for (const [k, v] of
|
|
1826
|
+
for (const [k, v] of dict) if (predicate(v)) res.set(k, v);
|
|
1539
1827
|
return res;
|
|
1540
1828
|
};
|
|
1541
|
-
|
|
1829
|
+
/**
|
|
1830
|
+
* Filters dictionary entries by a predicate that also receives the key.
|
|
1831
|
+
*
|
|
1832
|
+
* @see {@link filter} for filtering values without key access.
|
|
1833
|
+
*/
|
|
1834
|
+
const filterWithKey$1 = (predicate) => (dict) => {
|
|
1542
1835
|
const res = new globalThis.Map();
|
|
1543
|
-
for (const [k, v] of
|
|
1836
|
+
for (const [k, v] of dict) if (predicate(k, v)) res.set(k, v);
|
|
1544
1837
|
return res;
|
|
1545
1838
|
};
|
|
1546
|
-
|
|
1839
|
+
/**
|
|
1840
|
+
* Removes all `None` values from a dictionary, unwrapping `Some` values.
|
|
1841
|
+
*/
|
|
1842
|
+
const compact$1 = (dict) => {
|
|
1547
1843
|
const res = new globalThis.Map();
|
|
1548
|
-
for (const [k, v] of
|
|
1844
|
+
for (const [k, v] of dict) if (v.kind === "Some") res.set(k, v.value);
|
|
1549
1845
|
return res;
|
|
1550
1846
|
};
|
|
1551
|
-
|
|
1847
|
+
/**
|
|
1848
|
+
* Transforms values with a function returning `Maybe`, keeping only `Some` values.
|
|
1849
|
+
*
|
|
1850
|
+
* @see {@link filter} for filtering without transformation.
|
|
1851
|
+
*/
|
|
1852
|
+
const filterMap$2 = (transform) => (dict) => {
|
|
1552
1853
|
const res = new globalThis.Map();
|
|
1553
|
-
for (const [k, v] of
|
|
1554
|
-
const mb =
|
|
1854
|
+
for (const [k, v] of dict) {
|
|
1855
|
+
const mb = transform(v);
|
|
1555
1856
|
if (mb.kind === "Some") res.set(k, mb.value);
|
|
1556
1857
|
}
|
|
1557
1858
|
return res;
|
|
1558
1859
|
};
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1860
|
+
/**
|
|
1861
|
+
* Combines two dictionaries, preferring entries from `other` on key collisions.
|
|
1862
|
+
*
|
|
1863
|
+
* @see {@link intersection} for keeping only common keys.
|
|
1864
|
+
* @see {@link difference} for removing keys present in the other dictionary.
|
|
1865
|
+
*/
|
|
1866
|
+
const union$1 = (other) => (dict) => {
|
|
1867
|
+
if (dict.size === 0) return other;
|
|
1868
|
+
if (other.size === 0) return dict;
|
|
1869
|
+
const res = new globalThis.Map(dict);
|
|
1563
1870
|
for (const [k, v] of other) res.set(k, v);
|
|
1564
1871
|
return res;
|
|
1565
1872
|
};
|
|
1566
|
-
|
|
1873
|
+
/**
|
|
1874
|
+
* Returns a new dictionary containing only keys present in both dictionaries.
|
|
1875
|
+
*
|
|
1876
|
+
* @see {@link union} for combining all keys from both dictionaries.
|
|
1877
|
+
* @see {@link difference} for subtracting keys.
|
|
1878
|
+
*/
|
|
1879
|
+
const intersection$1 = (other) => (dict) => {
|
|
1567
1880
|
const res = new globalThis.Map();
|
|
1568
|
-
for (const [k, v] of
|
|
1881
|
+
for (const [k, v] of dict) if (other.has(k)) res.set(k, v);
|
|
1569
1882
|
return res;
|
|
1570
1883
|
};
|
|
1571
|
-
|
|
1572
|
-
|
|
1884
|
+
/**
|
|
1885
|
+
* Returns a new dictionary containing keys from `dict` that are not in `other`.
|
|
1886
|
+
*
|
|
1887
|
+
* @see {@link union} for combining all keys.
|
|
1888
|
+
* @see {@link intersection} for keeping only common keys.
|
|
1889
|
+
*/
|
|
1890
|
+
const difference$1 = (other) => (dict) => {
|
|
1891
|
+
if (other.size === 0) return dict;
|
|
1573
1892
|
const res = new globalThis.Map();
|
|
1574
|
-
for (const [k, v] of
|
|
1893
|
+
for (const [k, v] of dict) if (!other.has(k)) res.set(k, v);
|
|
1575
1894
|
return res;
|
|
1576
1895
|
};
|
|
1577
|
-
const reduce$1 = (
|
|
1578
|
-
let acc =
|
|
1579
|
-
for (const [, v] of
|
|
1896
|
+
const reduce$1 = (initial, reducer) => (dict) => {
|
|
1897
|
+
let acc = initial;
|
|
1898
|
+
for (const [, v] of dict) acc = reducer(acc, v);
|
|
1580
1899
|
return acc;
|
|
1581
1900
|
};
|
|
1582
|
-
const reduceWithKey = (
|
|
1583
|
-
let acc =
|
|
1584
|
-
for (const [k, v] of
|
|
1901
|
+
const reduceWithKey = (initial, reducer) => (dict) => {
|
|
1902
|
+
let acc = initial;
|
|
1903
|
+
for (const [k, v] of dict) acc = reducer(acc, v, k);
|
|
1585
1904
|
return acc;
|
|
1586
1905
|
};
|
|
1906
|
+
/**
|
|
1907
|
+
* Merges two dictionaries using a combination function on collisions.
|
|
1908
|
+
*/
|
|
1587
1909
|
function mergeWith$1(combine) {
|
|
1588
1910
|
return ((arg1, arg2) => {
|
|
1589
1911
|
if (arg2 !== void 0) {
|
|
@@ -1601,27 +1923,27 @@ function mergeWith$1(combine) {
|
|
|
1601
1923
|
};
|
|
1602
1924
|
});
|
|
1603
1925
|
}
|
|
1604
|
-
const mapEntries$1 = (
|
|
1926
|
+
const mapEntries$1 = (transform) => (dict) => {
|
|
1605
1927
|
const res = new globalThis.Map();
|
|
1606
|
-
for (const [k, v] of
|
|
1607
|
-
const [nk, nv] =
|
|
1928
|
+
for (const [k, v] of dict) {
|
|
1929
|
+
const [nk, nv] = transform(k, v);
|
|
1608
1930
|
res.set(nk, nv);
|
|
1609
1931
|
}
|
|
1610
1932
|
return res;
|
|
1611
1933
|
};
|
|
1612
|
-
const mapKeys$1 = (
|
|
1934
|
+
const mapKeys$1 = (transform) => (dict) => {
|
|
1613
1935
|
const res = new globalThis.Map();
|
|
1614
|
-
for (const [k, v] of
|
|
1936
|
+
for (const [k, v] of dict) res.set(transform(k), v);
|
|
1615
1937
|
return res;
|
|
1616
1938
|
};
|
|
1617
1939
|
const _nonEmptySingleton = (key, value) => new globalThis.Map([[key, value]]);
|
|
1618
|
-
const _nonEmptyFromMap = (
|
|
1619
|
-
const _nonEmptyKeys = (
|
|
1620
|
-
const _nonEmptyValues = (
|
|
1621
|
-
const _nonEmptyEntries = (
|
|
1622
|
-
const _nonEmptyReduce = (
|
|
1623
|
-
const _nonEmptyMap = (
|
|
1624
|
-
const _nonEmptyMapWithKey = (
|
|
1940
|
+
const _nonEmptyFromMap = (dict) => dict.size > 0 ? require_Core.Maybe.make.some(dict) : require_Core.Maybe.make.none();
|
|
1941
|
+
const _nonEmptyKeys = (dict) => keys$1(dict);
|
|
1942
|
+
const _nonEmptyValues = (dict) => values$1(dict);
|
|
1943
|
+
const _nonEmptyEntries = (dict) => entries$1(dict);
|
|
1944
|
+
const _nonEmptyReduce = (reducer) => (dict) => _nonEmptyValues(dict).reduce(reducer);
|
|
1945
|
+
const _nonEmptyMap = (transform) => (dict) => map$2(transform)(dict);
|
|
1946
|
+
const _nonEmptyMapWithKey = (transform) => (dict) => mapWithKey$1(transform)(dict);
|
|
1625
1947
|
const Dict = {
|
|
1626
1948
|
is: DictIs,
|
|
1627
1949
|
empty: empty$1,
|
|
@@ -1654,7 +1976,7 @@ const Dict = {
|
|
|
1654
1976
|
mapKeys: mapKeys$1,
|
|
1655
1977
|
NonEmpty: {
|
|
1656
1978
|
singleton: _nonEmptySingleton,
|
|
1657
|
-
from: {
|
|
1979
|
+
from: { map: _nonEmptyFromMap },
|
|
1658
1980
|
keys: _nonEmptyKeys,
|
|
1659
1981
|
values: _nonEmptyValues,
|
|
1660
1982
|
entries: _nonEmptyEntries,
|
|
@@ -1707,9 +2029,9 @@ const Json = {
|
|
|
1707
2029
|
};
|
|
1708
2030
|
//#endregion
|
|
1709
2031
|
//#region src/Data/Num.ts
|
|
1710
|
-
const sumFn = (
|
|
2032
|
+
const sumFn = (numbers) => {
|
|
1711
2033
|
let result = 0;
|
|
1712
|
-
for (let i = 0; i <
|
|
2034
|
+
for (let i = 0; i < numbers.length; i++) result += numbers[i];
|
|
1713
2035
|
return result;
|
|
1714
2036
|
};
|
|
1715
2037
|
const Num = {
|
|
@@ -1723,27 +2045,31 @@ const Num = {
|
|
|
1723
2045
|
* Num.is.zero(5); // false
|
|
1724
2046
|
* ```
|
|
1725
2047
|
*/
|
|
1726
|
-
zero: (
|
|
2048
|
+
zero: (value) => value === 0,
|
|
1727
2049
|
/**
|
|
1728
2050
|
* Returns `true` when the number is a whole integer.
|
|
1729
2051
|
*
|
|
2052
|
+
* @see {@link Num.is.float} to check for fractional numbers.
|
|
2053
|
+
*
|
|
1730
2054
|
* @example
|
|
1731
2055
|
* ```ts
|
|
1732
2056
|
* Num.is.integer(5); // true
|
|
1733
2057
|
* Num.is.integer(3.14); // false
|
|
1734
2058
|
* ```
|
|
1735
2059
|
*/
|
|
1736
|
-
integer: (
|
|
2060
|
+
integer: (value) => Number.isInteger(value),
|
|
1737
2061
|
/**
|
|
1738
2062
|
* Returns `true` when the number is a finite float (fractional number).
|
|
1739
2063
|
*
|
|
2064
|
+
* @see {@link Num.is.integer} to check for whole numbers.
|
|
2065
|
+
*
|
|
1740
2066
|
* @example
|
|
1741
2067
|
* ```ts
|
|
1742
2068
|
* Num.is.float(3.14); // true
|
|
1743
2069
|
* Num.is.float(5); // false
|
|
1744
2070
|
* ```
|
|
1745
2071
|
*/
|
|
1746
|
-
float: (
|
|
2072
|
+
float: (value) => Number.isFinite(value) && !Number.isInteger(value),
|
|
1747
2073
|
/**
|
|
1748
2074
|
* Returns `true` when the number is finite (not `Infinity`, `-Infinity`, or `NaN`).
|
|
1749
2075
|
*
|
|
@@ -1753,7 +2079,7 @@ const Num = {
|
|
|
1753
2079
|
* Num.is.finite(Infinity); // false
|
|
1754
2080
|
* ```
|
|
1755
2081
|
*/
|
|
1756
|
-
finite: (
|
|
2082
|
+
finite: (value) => Number.isFinite(value),
|
|
1757
2083
|
/**
|
|
1758
2084
|
* Returns `true` when the value is `NaN`.
|
|
1759
2085
|
*
|
|
@@ -1763,10 +2089,12 @@ const Num = {
|
|
|
1763
2089
|
* Num.is.nan(42); // false
|
|
1764
2090
|
* ```
|
|
1765
2091
|
*/
|
|
1766
|
-
nan: (
|
|
2092
|
+
nan: (value) => Number.isNaN(value),
|
|
1767
2093
|
/**
|
|
1768
2094
|
* Returns `true` when the number is an even integer.
|
|
1769
2095
|
*
|
|
2096
|
+
* @see {@link Num.is.odd} to check if a number is odd.
|
|
2097
|
+
*
|
|
1770
2098
|
* @example
|
|
1771
2099
|
* ```ts
|
|
1772
2100
|
* Num.is.even(4); // true
|
|
@@ -1774,10 +2102,12 @@ const Num = {
|
|
|
1774
2102
|
* Num.is.even(2.5); // false
|
|
1775
2103
|
* ```
|
|
1776
2104
|
*/
|
|
1777
|
-
even: (
|
|
2105
|
+
even: (value) => Number.isInteger(value) && value % 2 === 0,
|
|
1778
2106
|
/**
|
|
1779
2107
|
* Returns `true` when the number is an odd integer.
|
|
1780
2108
|
*
|
|
2109
|
+
* @see {@link Num.is.even} to check if a number is even.
|
|
2110
|
+
*
|
|
1781
2111
|
* @example
|
|
1782
2112
|
* ```ts
|
|
1783
2113
|
* Num.is.odd(3); // true
|
|
@@ -1785,10 +2115,12 @@ const Num = {
|
|
|
1785
2115
|
* Num.is.odd(2.5); // false
|
|
1786
2116
|
* ```
|
|
1787
2117
|
*/
|
|
1788
|
-
odd: (
|
|
2118
|
+
odd: (value) => Number.isInteger(value) && value % 2 !== 0,
|
|
1789
2119
|
/**
|
|
1790
2120
|
* Returns `true` when the number is strictly greater than zero.
|
|
1791
2121
|
*
|
|
2122
|
+
* @see {@link Num.is.negative} to check if a number is less than zero.
|
|
2123
|
+
*
|
|
1792
2124
|
* @example
|
|
1793
2125
|
* ```ts
|
|
1794
2126
|
* Num.is.positive(5); // true
|
|
@@ -1796,10 +2128,12 @@ const Num = {
|
|
|
1796
2128
|
* Num.is.positive(-5); // false
|
|
1797
2129
|
* ```
|
|
1798
2130
|
*/
|
|
1799
|
-
positive: (
|
|
2131
|
+
positive: (value) => value > 0,
|
|
1800
2132
|
/**
|
|
1801
2133
|
* Returns `true` when the number is strictly less than zero.
|
|
1802
2134
|
*
|
|
2135
|
+
* @see {@link Num.is.positive} to check if a number is greater than zero.
|
|
2136
|
+
*
|
|
1803
2137
|
* @example
|
|
1804
2138
|
* ```ts
|
|
1805
2139
|
* Num.is.negative(-5); // true
|
|
@@ -1807,7 +2141,7 @@ const Num = {
|
|
|
1807
2141
|
* Num.is.negative(5); // false
|
|
1808
2142
|
* ```
|
|
1809
2143
|
*/
|
|
1810
|
-
negative: (
|
|
2144
|
+
negative: (value) => value < 0
|
|
1811
2145
|
},
|
|
1812
2146
|
/**
|
|
1813
2147
|
* Generates an array of numbers from `from` to `to` (both inclusive),
|
|
@@ -1841,10 +2175,12 @@ const Num = {
|
|
|
1841
2175
|
* pipe(42, Num.clamp(0, 100)); // 42
|
|
1842
2176
|
* ```
|
|
1843
2177
|
*/
|
|
1844
|
-
clamp: (min, max) => (
|
|
2178
|
+
clamp: (min, max) => (value) => Math.min(Math.max(value, min), max),
|
|
1845
2179
|
/**
|
|
1846
2180
|
* Returns `true` when the number is between `min` and `max` (both inclusive).
|
|
1847
2181
|
*
|
|
2182
|
+
* @see {@link Num.inRange} for half-open range checking [start, end).
|
|
2183
|
+
*
|
|
1848
2184
|
* @example
|
|
1849
2185
|
* ```ts
|
|
1850
2186
|
* pipe(5, Num.between(1, 10)); // true
|
|
@@ -1852,10 +2188,12 @@ const Num = {
|
|
|
1852
2188
|
* pipe(10, Num.between(1, 10)); // true
|
|
1853
2189
|
* ```
|
|
1854
2190
|
*/
|
|
1855
|
-
between: (min, max) => (
|
|
2191
|
+
between: (min, max) => (value) => value >= min && value <= max,
|
|
1856
2192
|
/**
|
|
1857
2193
|
* Returns `true` when the number is in the range `[start, end)` (inclusive of `start`, exclusive of `end`).
|
|
1858
2194
|
*
|
|
2195
|
+
* @see {@link Num.between} for fully closed range checking [min, max].
|
|
2196
|
+
*
|
|
1859
2197
|
* @example
|
|
1860
2198
|
* ```ts
|
|
1861
2199
|
* pipe(5, Num.inRange(1, 10)); // true
|
|
@@ -1863,7 +2201,7 @@ const Num = {
|
|
|
1863
2201
|
* pipe(10, Num.inRange(1, 10)); // false
|
|
1864
2202
|
* ```
|
|
1865
2203
|
*/
|
|
1866
|
-
inRange: (start, end) => (
|
|
2204
|
+
inRange: (start, end) => (value) => value >= start && value < end,
|
|
1867
2205
|
/**
|
|
1868
2206
|
* Parses a string as a number. Returns `None` when the result is `NaN`.
|
|
1869
2207
|
*
|
|
@@ -1875,13 +2213,15 @@ const Num = {
|
|
|
1875
2213
|
* Num.parse(""); // None
|
|
1876
2214
|
* ```
|
|
1877
2215
|
*/
|
|
1878
|
-
parse: (
|
|
1879
|
-
if (
|
|
1880
|
-
const n = Number(
|
|
2216
|
+
parse: (text) => {
|
|
2217
|
+
if (text.trim() === "") return require_Core.Maybe.make.none();
|
|
2218
|
+
const n = Number(text);
|
|
1881
2219
|
return isNaN(n) ? require_Core.Maybe.make.none() : require_Core.Maybe.make.some(n);
|
|
1882
2220
|
},
|
|
1883
2221
|
/**
|
|
1884
|
-
* Adds `
|
|
2222
|
+
* Adds `amount` to a number. Data-last: use in `pipe` or `Arr.map`.
|
|
2223
|
+
*
|
|
2224
|
+
* @see {@link Num.subtract} to subtract an amount from a number.
|
|
1885
2225
|
*
|
|
1886
2226
|
* @example
|
|
1887
2227
|
* ```ts
|
|
@@ -1889,9 +2229,11 @@ const Num = {
|
|
|
1889
2229
|
* pipe([1, 2, 3], Arr.map(Num.add(10))); // [11, 12, 13]
|
|
1890
2230
|
* ```
|
|
1891
2231
|
*/
|
|
1892
|
-
add: (
|
|
2232
|
+
add: (amount) => (value) => value + amount,
|
|
1893
2233
|
/**
|
|
1894
|
-
* Subtracts `
|
|
2234
|
+
* Subtracts `amount` from a number. Data-last: `subtract(amount)(from)` = `from - amount`.
|
|
2235
|
+
*
|
|
2236
|
+
* @see {@link Num.add} to add an amount to a number.
|
|
1895
2237
|
*
|
|
1896
2238
|
* @example
|
|
1897
2239
|
* ```ts
|
|
@@ -1899,9 +2241,11 @@ const Num = {
|
|
|
1899
2241
|
* pipe([5, 10, 15], Arr.map(Num.subtract(2))); // [3, 8, 13]
|
|
1900
2242
|
* ```
|
|
1901
2243
|
*/
|
|
1902
|
-
subtract: (
|
|
2244
|
+
subtract: (amount) => (from) => from - amount,
|
|
1903
2245
|
/**
|
|
1904
|
-
* Multiplies a number by `
|
|
2246
|
+
* Multiplies a number by `factor`. Data-last: use in `pipe` or `Arr.map`.
|
|
2247
|
+
*
|
|
2248
|
+
* @see {@link Num.divide} to divide a number by a divisor.
|
|
1905
2249
|
*
|
|
1906
2250
|
* @example
|
|
1907
2251
|
* ```ts
|
|
@@ -1909,9 +2253,12 @@ const Num = {
|
|
|
1909
2253
|
* pipe([1, 2, 3], Arr.map(Num.multiply(100))); // [100, 200, 300]
|
|
1910
2254
|
* ```
|
|
1911
2255
|
*/
|
|
1912
|
-
multiply: (
|
|
2256
|
+
multiply: (factor) => (value) => value * factor,
|
|
1913
2257
|
/**
|
|
1914
|
-
* Divides a number by `
|
|
2258
|
+
* Divides a number by `divisor`. Returns `None` when `divisor` is zero. Data-last: `divide(divisor)(dividend)` = `dividend / divisor`.
|
|
2259
|
+
*
|
|
2260
|
+
* @see {@link Num.multiply} to multiply a number by a factor.
|
|
2261
|
+
* @see {@link Num.remainder} to compute the division remainder.
|
|
1915
2262
|
*
|
|
1916
2263
|
* @example
|
|
1917
2264
|
* ```ts
|
|
@@ -1920,7 +2267,7 @@ const Num = {
|
|
|
1920
2267
|
* pipe([10, 20, 30], Arr.filterMap(Num.divide(10))); // [1, 2, 3]
|
|
1921
2268
|
* ```
|
|
1922
2269
|
*/
|
|
1923
|
-
divide: (
|
|
2270
|
+
divide: (divisor) => (dividend) => divisor === 0 ? require_Core.Maybe.make.none() : require_Core.Maybe.make.some(dividend / divisor),
|
|
1924
2271
|
/**
|
|
1925
2272
|
* Returns the absolute value of a number.
|
|
1926
2273
|
*
|
|
@@ -1930,7 +2277,7 @@ const Num = {
|
|
|
1930
2277
|
* pipe(5, Num.abs); // 5
|
|
1931
2278
|
* ```
|
|
1932
2279
|
*/
|
|
1933
|
-
abs: (
|
|
2280
|
+
abs: (value) => Math.abs(value),
|
|
1934
2281
|
/**
|
|
1935
2282
|
* Negates a number (arithmetic negation).
|
|
1936
2283
|
*
|
|
@@ -1940,40 +2287,51 @@ const Num = {
|
|
|
1940
2287
|
* pipe(-5, Num.negate); // 5
|
|
1941
2288
|
* ```
|
|
1942
2289
|
*/
|
|
1943
|
-
negate: (
|
|
2290
|
+
negate: (value) => -value,
|
|
1944
2291
|
/**
|
|
1945
2292
|
* Rounds a number to the nearest integer.
|
|
1946
2293
|
*
|
|
2294
|
+
* @see {@link Num.floor} to round down.
|
|
2295
|
+
* @see {@link Num.ceil} to round up.
|
|
2296
|
+
*
|
|
1947
2297
|
* @example
|
|
1948
2298
|
* ```ts
|
|
1949
2299
|
* pipe(3.5, Num.round); // 4
|
|
1950
2300
|
* pipe(3.4, Num.round); // 3
|
|
1951
2301
|
* ```
|
|
1952
2302
|
*/
|
|
1953
|
-
round: (
|
|
2303
|
+
round: (value) => Math.round(value),
|
|
1954
2304
|
/**
|
|
1955
2305
|
* Rounds a number down to the nearest integer.
|
|
1956
2306
|
*
|
|
2307
|
+
* @see {@link Num.round} to round to nearest integer.
|
|
2308
|
+
* @see {@link Num.ceil} to round up.
|
|
2309
|
+
*
|
|
1957
2310
|
* @example
|
|
1958
2311
|
* ```ts
|
|
1959
2312
|
* pipe(3.9, Num.floor); // 3
|
|
1960
2313
|
* pipe(-3.2, Num.floor); // -4
|
|
1961
2314
|
* ```
|
|
1962
2315
|
*/
|
|
1963
|
-
floor: (
|
|
2316
|
+
floor: (value) => Math.floor(value),
|
|
1964
2317
|
/**
|
|
1965
2318
|
* Rounds a number up to the nearest integer.
|
|
1966
2319
|
*
|
|
2320
|
+
* @see {@link Num.round} to round to nearest integer.
|
|
2321
|
+
* @see {@link Num.floor} to round down.
|
|
2322
|
+
*
|
|
1967
2323
|
* @example
|
|
1968
2324
|
* ```ts
|
|
1969
2325
|
* pipe(3.1, Num.ceil); // 4
|
|
1970
2326
|
* pipe(-3.9, Num.ceil); // -3
|
|
1971
2327
|
* ```
|
|
1972
2328
|
*/
|
|
1973
|
-
ceil: (
|
|
2329
|
+
ceil: (value) => Math.ceil(value),
|
|
1974
2330
|
/**
|
|
1975
2331
|
* Returns the remainder of dividing a number by `divisor`. Returns `None` when `divisor` is zero.
|
|
1976
|
-
* Data-last: `remainder(divisor)(
|
|
2332
|
+
* Data-last: `remainder(divisor)(dividend)` = `dividend % divisor`.
|
|
2333
|
+
*
|
|
2334
|
+
* @see {@link Num.divide} for full division.
|
|
1977
2335
|
*
|
|
1978
2336
|
* @example
|
|
1979
2337
|
* ```ts
|
|
@@ -1982,7 +2340,7 @@ const Num = {
|
|
|
1982
2340
|
* pipe([10, 11, 12], Arr.filterMap(Num.remainder(3))); // [1, 2, 0]
|
|
1983
2341
|
* ```
|
|
1984
2342
|
*/
|
|
1985
|
-
remainder: (divisor) => (
|
|
2343
|
+
remainder: (divisor) => (dividend) => divisor === 0 ? require_Core.Maybe.make.none() : require_Core.Maybe.make.some(dividend % divisor),
|
|
1986
2344
|
/**
|
|
1987
2345
|
* Computes the sum of a list of numbers. Returns `0` if the list is empty.
|
|
1988
2346
|
*
|
|
@@ -2002,39 +2360,43 @@ const Num = {
|
|
|
2002
2360
|
* Num.mean([]); // None
|
|
2003
2361
|
* ```
|
|
2004
2362
|
*/
|
|
2005
|
-
mean: (
|
|
2363
|
+
mean: (numbers) => numbers.length === 0 ? require_Core.Maybe.make.none() : require_Core.Maybe.make.some(sumFn(numbers) / numbers.length),
|
|
2006
2364
|
/**
|
|
2007
2365
|
* Computes the minimum of a list of numbers. Returns `None` if the list is empty.
|
|
2008
2366
|
*
|
|
2367
|
+
* @see {@link Num.max} to compute the maximum value.
|
|
2368
|
+
*
|
|
2009
2369
|
* @example
|
|
2010
2370
|
* ```ts
|
|
2011
2371
|
* Num.min([5, 1, 3]); // Some(1)
|
|
2012
2372
|
* Num.min([]); // None
|
|
2013
2373
|
* ```
|
|
2014
2374
|
*/
|
|
2015
|
-
min: (
|
|
2016
|
-
if (
|
|
2017
|
-
let [result] =
|
|
2018
|
-
for (let i = 1; i <
|
|
2375
|
+
min: (numbers) => {
|
|
2376
|
+
if (numbers.length === 0) return require_Core.Maybe.make.none();
|
|
2377
|
+
let [result] = numbers;
|
|
2378
|
+
for (let i = 1; i < numbers.length; i++) if (numbers[i] < result) result = numbers[i];
|
|
2019
2379
|
return require_Core.Maybe.make.some(result);
|
|
2020
2380
|
},
|
|
2021
2381
|
/**
|
|
2022
2382
|
* Computes the maximum of a list of numbers. Returns `None` if the list is empty.
|
|
2023
2383
|
*
|
|
2384
|
+
* @see {@link Num.min} to compute the minimum value.
|
|
2385
|
+
*
|
|
2024
2386
|
* @example
|
|
2025
2387
|
* ```ts
|
|
2026
2388
|
* Num.max([1, 5, 3]); // Some(5)
|
|
2027
2389
|
* Num.max([]); // None
|
|
2028
2390
|
* ```
|
|
2029
2391
|
*/
|
|
2030
|
-
max: (
|
|
2031
|
-
if (
|
|
2032
|
-
let [result] =
|
|
2033
|
-
for (let i = 1; i <
|
|
2392
|
+
max: (numbers) => {
|
|
2393
|
+
if (numbers.length === 0) return require_Core.Maybe.make.none();
|
|
2394
|
+
let [result] = numbers;
|
|
2395
|
+
for (let i = 1; i < numbers.length; i++) if (numbers[i] > result) result = numbers[i];
|
|
2034
2396
|
return require_Core.Maybe.make.some(result);
|
|
2035
2397
|
},
|
|
2036
2398
|
/**
|
|
2037
|
-
* Formats a number using `Intl.NumberFormat`. Returns `None` when `
|
|
2399
|
+
* Formats a number using `Intl.NumberFormat`. Returns `None` when `value` is `NaN` or non-finite.
|
|
2038
2400
|
* Data-last curried signature.
|
|
2039
2401
|
*
|
|
2040
2402
|
* @example
|
|
@@ -2044,11 +2406,11 @@ const Num = {
|
|
|
2044
2406
|
* pipe(NaN, formatCurrency); // None
|
|
2045
2407
|
* ```
|
|
2046
2408
|
*/
|
|
2047
|
-
format: (options, locales) => (
|
|
2409
|
+
format: (options, locales) => (value) => !Number.isFinite(value) ? require_Core.Maybe.make.none() : require_Core.Maybe.make.some(new Intl.NumberFormat(locales, options).format(value))
|
|
2048
2410
|
};
|
|
2049
2411
|
//#endregion
|
|
2050
2412
|
//#region src/Data/Rec.ts
|
|
2051
|
-
const _isNonEmpty = (
|
|
2413
|
+
const _isNonEmpty = (record) => Object.keys(record).length > 0;
|
|
2052
2414
|
const _setKey = (record, key, value) => {
|
|
2053
2415
|
if (key === "__proto__") Object.defineProperty(record, key, {
|
|
2054
2416
|
value,
|
|
@@ -2060,8 +2422,8 @@ const _setKey = (record, key, value) => {
|
|
|
2060
2422
|
};
|
|
2061
2423
|
let RecMaybe;
|
|
2062
2424
|
(function(_RecMaybe) {
|
|
2063
|
-
const traverse = _RecMaybe.traverse = (
|
|
2064
|
-
const recordKeys = Object.keys(
|
|
2425
|
+
const traverse = _RecMaybe.traverse = (transform) => (record) => {
|
|
2426
|
+
const recordKeys = Object.keys(record);
|
|
2065
2427
|
if (recordKeys.length === 0) return {
|
|
2066
2428
|
kind: "Some",
|
|
2067
2429
|
value: {}
|
|
@@ -2069,7 +2431,7 @@ let RecMaybe;
|
|
|
2069
2431
|
const result = {};
|
|
2070
2432
|
for (let i = 0; i < recordKeys.length; i++) {
|
|
2071
2433
|
const key = recordKeys[i];
|
|
2072
|
-
const maybeVal =
|
|
2434
|
+
const maybeVal = transform(record[key]);
|
|
2073
2435
|
if (maybeVal.kind === "None") return maybeVal;
|
|
2074
2436
|
_setKey(result, key, maybeVal.value);
|
|
2075
2437
|
}
|
|
@@ -2078,16 +2440,16 @@ let RecMaybe;
|
|
|
2078
2440
|
value: result
|
|
2079
2441
|
};
|
|
2080
2442
|
};
|
|
2081
|
-
_RecMaybe.sequence = (
|
|
2443
|
+
_RecMaybe.sequence = (record) => traverse((value) => value)(record);
|
|
2082
2444
|
})(RecMaybe || (RecMaybe = {}));
|
|
2083
2445
|
let RecResult;
|
|
2084
2446
|
(function(_RecResult) {
|
|
2085
|
-
const traverse = _RecResult.traverse = (
|
|
2086
|
-
const recordKeys = Object.keys(
|
|
2447
|
+
const traverse = _RecResult.traverse = (transform) => (record) => {
|
|
2448
|
+
const recordKeys = Object.keys(record);
|
|
2087
2449
|
const result = {};
|
|
2088
2450
|
for (let i = 0; i < recordKeys.length; i++) {
|
|
2089
2451
|
const key = recordKeys[i];
|
|
2090
|
-
const res =
|
|
2452
|
+
const res = transform(record[key]);
|
|
2091
2453
|
if (res.kind === "Err") return res;
|
|
2092
2454
|
_setKey(result, key, res.value);
|
|
2093
2455
|
}
|
|
@@ -2096,7 +2458,7 @@ let RecResult;
|
|
|
2096
2458
|
value: result
|
|
2097
2459
|
};
|
|
2098
2460
|
};
|
|
2099
|
-
_RecResult.sequence = (
|
|
2461
|
+
_RecResult.sequence = (record) => traverse((value) => value)(record);
|
|
2100
2462
|
})(RecResult || (RecResult = {}));
|
|
2101
2463
|
/**
|
|
2102
2464
|
* Functional record/object utilities that compose well with pipe.
|
|
@@ -2118,16 +2480,20 @@ const RecIs = {
|
|
|
2118
2480
|
/**
|
|
2119
2481
|
* Returns true if the record has no keys.
|
|
2120
2482
|
*
|
|
2483
|
+
* @see {@link nonEmpty} for checking if a record has keys.
|
|
2484
|
+
*
|
|
2121
2485
|
* @example
|
|
2122
2486
|
* ```ts
|
|
2123
2487
|
* Rec.is.empty({}); // true
|
|
2124
2488
|
* Rec.is.empty({ a: 1 }); // false
|
|
2125
2489
|
* ```
|
|
2126
2490
|
*/
|
|
2127
|
-
empty: (
|
|
2491
|
+
empty: (record) => Object.keys(record).length === 0,
|
|
2128
2492
|
/**
|
|
2129
2493
|
* Type guard to check if a record is non-empty.
|
|
2130
2494
|
*
|
|
2495
|
+
* @see {@link empty} for checking if a record has no keys.
|
|
2496
|
+
*
|
|
2131
2497
|
* @example
|
|
2132
2498
|
* ```ts
|
|
2133
2499
|
* Rec.is.nonEmpty({ a: 1 }); // true
|
|
@@ -2139,30 +2505,36 @@ const RecIs = {
|
|
|
2139
2505
|
/**
|
|
2140
2506
|
* Transforms each value in a record.
|
|
2141
2507
|
*
|
|
2508
|
+
* @see {@link mapWithKey} for transforming values with key access.
|
|
2509
|
+
* @see {@link mapKeys} for transforming keys while preserving values.
|
|
2510
|
+
* @see {@link mapEntries} for transforming keys and values simultaneously.
|
|
2511
|
+
*
|
|
2142
2512
|
* @example
|
|
2143
2513
|
* ```ts
|
|
2144
2514
|
* pipe({ a: 1, b: 2 }, Rec.map(n => n * 2)); // { a: 2, b: 4 }
|
|
2145
2515
|
* ```
|
|
2146
2516
|
*/
|
|
2147
|
-
const map$1 = (
|
|
2148
|
-
const recordKeys = Object.keys(
|
|
2149
|
-
const recordValues = Object.values(
|
|
2150
|
-
const result = Object.create(Object.getPrototypeOf(
|
|
2517
|
+
const map$1 = (transform) => (record) => {
|
|
2518
|
+
const recordKeys = Object.keys(record);
|
|
2519
|
+
const recordValues = Object.values(record);
|
|
2520
|
+
const result = Object.create(Object.getPrototypeOf(record));
|
|
2151
2521
|
for (let i = 0; i < recordKeys.length; i++) {
|
|
2152
2522
|
const key = recordKeys[i];
|
|
2153
2523
|
if (key === "__proto__") Object.defineProperty(result, "__proto__", {
|
|
2154
|
-
value:
|
|
2524
|
+
value: transform(recordValues[i]),
|
|
2155
2525
|
writable: true,
|
|
2156
2526
|
enumerable: true,
|
|
2157
2527
|
configurable: true
|
|
2158
2528
|
});
|
|
2159
|
-
else result[key] =
|
|
2529
|
+
else result[key] = transform(recordValues[i]);
|
|
2160
2530
|
}
|
|
2161
2531
|
return result;
|
|
2162
2532
|
};
|
|
2163
2533
|
/**
|
|
2164
2534
|
* Maps each value in a record with a function returning a `Maybe`, keeping only `Some` values.
|
|
2165
2535
|
*
|
|
2536
|
+
* @see {@link filter} for filtering with a boolean predicate.
|
|
2537
|
+
*
|
|
2166
2538
|
* @example
|
|
2167
2539
|
* ```ts
|
|
2168
2540
|
* pipe(
|
|
@@ -2171,12 +2543,12 @@ const map$1 = (f) => (data) => {
|
|
|
2171
2543
|
* ); // { b: 20 }
|
|
2172
2544
|
* ```
|
|
2173
2545
|
*/
|
|
2174
|
-
const filterMap$1 = (
|
|
2175
|
-
const recordKeys = Object.keys(
|
|
2176
|
-
const recordValues = Object.values(
|
|
2177
|
-
const result = Object.create(Object.getPrototypeOf(
|
|
2546
|
+
const filterMap$1 = (transform) => (record) => {
|
|
2547
|
+
const recordKeys = Object.keys(record);
|
|
2548
|
+
const recordValues = Object.values(record);
|
|
2549
|
+
const result = Object.create(Object.getPrototypeOf(record));
|
|
2178
2550
|
for (let i = 0; i < recordKeys.length; i++) {
|
|
2179
|
-
const maybeVal =
|
|
2551
|
+
const maybeVal = transform(recordValues[i]);
|
|
2180
2552
|
if (maybeVal.kind === "Some") _setKey(result, recordKeys[i], maybeVal.value);
|
|
2181
2553
|
}
|
|
2182
2554
|
return result;
|
|
@@ -2184,49 +2556,56 @@ const filterMap$1 = (f) => (data) => {
|
|
|
2184
2556
|
/**
|
|
2185
2557
|
* Transforms each value in a record, also receiving the key.
|
|
2186
2558
|
*
|
|
2559
|
+
* @see {@link map} for transforming values without key access.
|
|
2560
|
+
*
|
|
2187
2561
|
* @example
|
|
2188
2562
|
* ```ts
|
|
2189
2563
|
* pipe({ a: 1, b: 2 }, Rec.mapWithKey((k, v) => `${k}:${v}`));
|
|
2190
2564
|
* // { a: "a:1", b: "b:2" }
|
|
2191
2565
|
* ```
|
|
2192
2566
|
*/
|
|
2193
|
-
const mapWithKey = (
|
|
2194
|
-
const recordKeys = Object.keys(
|
|
2195
|
-
const recordValues = Object.values(
|
|
2196
|
-
const result = Object.create(Object.getPrototypeOf(
|
|
2567
|
+
const mapWithKey = (transform) => (record) => {
|
|
2568
|
+
const recordKeys = Object.keys(record);
|
|
2569
|
+
const recordValues = Object.values(record);
|
|
2570
|
+
const result = Object.create(Object.getPrototypeOf(record));
|
|
2197
2571
|
for (let i = 0; i < recordKeys.length; i++) {
|
|
2198
2572
|
const key = recordKeys[i];
|
|
2199
|
-
_setKey(result, key,
|
|
2573
|
+
_setKey(result, key, transform(key, recordValues[i]));
|
|
2200
2574
|
}
|
|
2201
2575
|
return result;
|
|
2202
2576
|
};
|
|
2203
2577
|
/**
|
|
2204
2578
|
* Filters values in a record by a predicate.
|
|
2205
2579
|
*
|
|
2580
|
+
* @see {@link filterWithKey} for filtering values with key access.
|
|
2581
|
+
* @see {@link filterMap} for filtering and mapping in a single pass.
|
|
2582
|
+
*
|
|
2206
2583
|
* @example
|
|
2207
2584
|
* ```ts
|
|
2208
2585
|
* pipe({ a: 1, b: 2, c: 3 }, Rec.filter(n => n > 1)); // { b: 2, c: 3 }
|
|
2209
2586
|
* ```
|
|
2210
2587
|
*/
|
|
2211
|
-
const filter$1 = (predicate) => (
|
|
2212
|
-
const recordKeys = Object.keys(
|
|
2213
|
-
const recordValues = Object.values(
|
|
2214
|
-
const result = Object.create(Object.getPrototypeOf(
|
|
2588
|
+
const filter$1 = (predicate) => (record) => {
|
|
2589
|
+
const recordKeys = Object.keys(record);
|
|
2590
|
+
const recordValues = Object.values(record);
|
|
2591
|
+
const result = Object.create(Object.getPrototypeOf(record));
|
|
2215
2592
|
for (let i = 0; i < recordKeys.length; i++) if (predicate(recordValues[i])) _setKey(result, recordKeys[i], recordValues[i]);
|
|
2216
2593
|
return result;
|
|
2217
2594
|
};
|
|
2218
2595
|
/**
|
|
2219
2596
|
* Filters values in a record by a predicate that also receives the key.
|
|
2220
2597
|
*
|
|
2598
|
+
* @see {@link filter} for filtering values without key access.
|
|
2599
|
+
*
|
|
2221
2600
|
* @example
|
|
2222
2601
|
* ```ts
|
|
2223
2602
|
* pipe({ a: 1, b: 2, c: 3 }, Rec.filterWithKey((k, v) => k !== "a" && v > 0));
|
|
2224
2603
|
* // { b: 2 }
|
|
2225
2604
|
* ```
|
|
2226
2605
|
*/
|
|
2227
|
-
const filterWithKey = (predicate) => (
|
|
2606
|
+
const filterWithKey = (predicate) => (record) => {
|
|
2228
2607
|
const result = {};
|
|
2229
|
-
for (const [k, v] of Object.entries(
|
|
2608
|
+
for (const [k, v] of Object.entries(record)) if (predicate(k, v)) _setKey(result, k, v);
|
|
2230
2609
|
return result;
|
|
2231
2610
|
};
|
|
2232
2611
|
/**
|
|
@@ -2238,37 +2617,46 @@ const filterWithKey = (predicate) => (data) => {
|
|
|
2238
2617
|
* pipe({ a: 1, b: 2 }, Rec.lookup("c")); // None
|
|
2239
2618
|
* ```
|
|
2240
2619
|
*/
|
|
2241
|
-
const lookup = (key) => (
|
|
2620
|
+
const lookup = (key) => (record) => Object.hasOwn(record, key) ? {
|
|
2242
2621
|
kind: "Some",
|
|
2243
|
-
value:
|
|
2622
|
+
value: record[key]
|
|
2244
2623
|
} : { kind: "None" };
|
|
2245
2624
|
/**
|
|
2246
2625
|
* Returns all keys of a record.
|
|
2247
2626
|
*
|
|
2627
|
+
* @see {@link values} for extracting record values.
|
|
2628
|
+
* @see {@link entries} for extracting key-value pairs.
|
|
2629
|
+
*
|
|
2248
2630
|
* @example
|
|
2249
2631
|
* ```ts
|
|
2250
2632
|
* Rec.keys({ a: 1, b: 2 }); // ["a", "b"]
|
|
2251
2633
|
* ```
|
|
2252
2634
|
*/
|
|
2253
|
-
const keys = (
|
|
2635
|
+
const keys = (record) => Object.keys(record);
|
|
2254
2636
|
/**
|
|
2255
2637
|
* Returns all values of a record.
|
|
2256
2638
|
*
|
|
2639
|
+
* @see {@link keys} for extracting record keys.
|
|
2640
|
+
* @see {@link entries} for extracting key-value pairs.
|
|
2641
|
+
*
|
|
2257
2642
|
* @example
|
|
2258
2643
|
* ```ts
|
|
2259
2644
|
* Rec.values({ a: 1, b: 2 }); // [1, 2]
|
|
2260
2645
|
* ```
|
|
2261
2646
|
*/
|
|
2262
|
-
const values = (
|
|
2647
|
+
const values = (record) => Object.values(record);
|
|
2263
2648
|
/**
|
|
2264
2649
|
* Returns all key-value pairs of a record.
|
|
2265
2650
|
*
|
|
2651
|
+
* @see {@link keys} for extracting record keys.
|
|
2652
|
+
* @see {@link values} for extracting record values.
|
|
2653
|
+
*
|
|
2266
2654
|
* @example
|
|
2267
2655
|
* ```ts
|
|
2268
2656
|
* Rec.entries({ a: 1, b: 2 }); // [["a", 1], ["b", 2]]
|
|
2269
2657
|
* ```
|
|
2270
2658
|
*/
|
|
2271
|
-
const entries = (
|
|
2659
|
+
const entries = (record) => Object.entries(record);
|
|
2272
2660
|
const RecFrom = {
|
|
2273
2661
|
/**
|
|
2274
2662
|
* Creates a record from key-value pairs.
|
|
@@ -2278,9 +2666,9 @@ const RecFrom = {
|
|
|
2278
2666
|
* Rec.from.entries([["a", 1], ["b", 2]]); // { a: 1, b: 2 }
|
|
2279
2667
|
* ```
|
|
2280
2668
|
*/
|
|
2281
|
-
entries: (
|
|
2669
|
+
entries: (pairs) => Object.fromEntries(pairs) };
|
|
2282
2670
|
/**
|
|
2283
|
-
* Groups elements of an array into a record keyed by the result of `
|
|
2671
|
+
* Groups elements of an array into a record keyed by the result of `keySelector`. Each key maps to
|
|
2284
2672
|
* the array of elements that produced it, in insertion order.
|
|
2285
2673
|
*
|
|
2286
2674
|
* Unlike `Dict.groupBy`, keys are always strings. Use `Dict.groupBy` when you need non-string
|
|
@@ -2294,10 +2682,10 @@ entries: (data) => Object.fromEntries(data) };
|
|
|
2294
2682
|
* ); // { a: ["apple", "avocado"], b: ["banana", "blueberry"] }
|
|
2295
2683
|
* ```
|
|
2296
2684
|
*/
|
|
2297
|
-
const groupBy = (
|
|
2685
|
+
const groupBy = (keySelector) => (items) => {
|
|
2298
2686
|
const result = {};
|
|
2299
2687
|
for (const item of items) {
|
|
2300
|
-
const key =
|
|
2688
|
+
const key = keySelector(item);
|
|
2301
2689
|
if (Object.hasOwn(result, key)) result[key].push(item);
|
|
2302
2690
|
else _setKey(result, key, [item]);
|
|
2303
2691
|
}
|
|
@@ -2306,40 +2694,46 @@ const groupBy = (keyFn) => (items) => {
|
|
|
2306
2694
|
/**
|
|
2307
2695
|
* Picks specific keys from a record.
|
|
2308
2696
|
*
|
|
2697
|
+
* @see {@link omit} for removing specific keys from a record.
|
|
2698
|
+
*
|
|
2309
2699
|
* @example
|
|
2310
2700
|
* ```ts
|
|
2311
2701
|
* pipe({ a: 1, b: 2, c: 3 }, Rec.pick("a", "c")); // { a: 1, c: 3 }
|
|
2312
2702
|
* ```
|
|
2313
2703
|
*/
|
|
2314
|
-
const pick = (...pickedKeys) => (
|
|
2704
|
+
const pick = (...pickedKeys) => (record) => {
|
|
2315
2705
|
const result = {};
|
|
2316
|
-
for (const key of pickedKeys) if (Object.hasOwn(
|
|
2706
|
+
for (const key of pickedKeys) if (Object.hasOwn(record, key)) _setKey(result, key, record[key]);
|
|
2317
2707
|
return result;
|
|
2318
2708
|
};
|
|
2319
2709
|
/**
|
|
2320
2710
|
* Omits specific keys from a record.
|
|
2321
2711
|
*
|
|
2712
|
+
* @see {@link pick} for retaining only specific keys from a record.
|
|
2713
|
+
*
|
|
2322
2714
|
* @example
|
|
2323
2715
|
* ```ts
|
|
2324
2716
|
* pipe({ a: 1, b: 2, c: 3 }, Rec.omit("b")); // { a: 1, c: 3 }
|
|
2325
2717
|
* ```
|
|
2326
2718
|
*/
|
|
2327
|
-
const omit = (...omittedKeys) => (
|
|
2719
|
+
const omit = (...omittedKeys) => (record) => {
|
|
2328
2720
|
const omitSet = new Set(omittedKeys);
|
|
2329
2721
|
const result = {};
|
|
2330
|
-
for (const key of Object.keys(
|
|
2722
|
+
for (const key of Object.keys(record)) if (!omitSet.has(key)) _setKey(result, key, record[key]);
|
|
2331
2723
|
return result;
|
|
2332
2724
|
};
|
|
2333
2725
|
/**
|
|
2334
2726
|
* Merges two records. Values from the second record take precedence.
|
|
2335
2727
|
*
|
|
2728
|
+
* @see {@link mergeWith} for merging records with custom collision resolution.
|
|
2729
|
+
*
|
|
2336
2730
|
* @example
|
|
2337
2731
|
* ```ts
|
|
2338
2732
|
* pipe({ a: 1, b: 2 }, Rec.merge({ b: 3, c: 4 })); // { a: 1, b: 3, c: 4 }
|
|
2339
2733
|
* ```
|
|
2340
2734
|
*/
|
|
2341
|
-
const merge = (other) => (
|
|
2342
|
-
...
|
|
2735
|
+
const merge = (other) => (record) => ({
|
|
2736
|
+
...record,
|
|
2343
2737
|
...other
|
|
2344
2738
|
});
|
|
2345
2739
|
function mergeWith(combine) {
|
|
@@ -2369,24 +2763,27 @@ function mergeWith(combine) {
|
|
|
2369
2763
|
* Rec.size({ a: 1, b: 2 }); // 2
|
|
2370
2764
|
* ```
|
|
2371
2765
|
*/
|
|
2372
|
-
const size$1 = (
|
|
2766
|
+
const size$1 = (record) => Object.keys(record).length;
|
|
2373
2767
|
/**
|
|
2374
2768
|
* Transforms each key while preserving values.
|
|
2375
2769
|
* If two keys map to the same new key, the last one wins.
|
|
2376
2770
|
*
|
|
2771
|
+
* @see {@link map} for transforming values.
|
|
2772
|
+
* @see {@link mapEntries} for transforming keys and values simultaneously.
|
|
2773
|
+
*
|
|
2377
2774
|
* @example
|
|
2378
2775
|
* ```ts
|
|
2379
2776
|
* pipe({ firstName: "Alice", lastName: "Smith" }, Rec.mapKeys(k => k.toUpperCase()));
|
|
2380
2777
|
* // { FIRSTNAME: "Alice", LASTNAME: "Smith" }
|
|
2381
2778
|
* ```
|
|
2382
2779
|
*/
|
|
2383
|
-
const mapKeys = (
|
|
2384
|
-
const recKeys = Object.keys(
|
|
2385
|
-
if (recKeys.length === 0) return
|
|
2780
|
+
const mapKeys = (transform) => (record) => {
|
|
2781
|
+
const recKeys = Object.keys(record);
|
|
2782
|
+
if (recKeys.length === 0) return record;
|
|
2386
2783
|
const result = {};
|
|
2387
2784
|
for (let i = 0; i < recKeys.length; i++) {
|
|
2388
2785
|
const k = recKeys[i];
|
|
2389
|
-
_setKey(result,
|
|
2786
|
+
_setKey(result, transform(k), record[k]);
|
|
2390
2787
|
}
|
|
2391
2788
|
return result;
|
|
2392
2789
|
};
|
|
@@ -2400,13 +2797,13 @@ const mapKeys = (f) => (data) => {
|
|
|
2400
2797
|
* // { a: 1, c: 3 }
|
|
2401
2798
|
* ```
|
|
2402
2799
|
*/
|
|
2403
|
-
const compact = (
|
|
2404
|
-
const recKeys = Object.keys(
|
|
2800
|
+
const compact = (record) => {
|
|
2801
|
+
const recKeys = Object.keys(record);
|
|
2405
2802
|
if (recKeys.length === 0) return {};
|
|
2406
2803
|
const result = {};
|
|
2407
2804
|
for (let i = 0; i < recKeys.length; i++) {
|
|
2408
2805
|
const k = recKeys[i];
|
|
2409
|
-
const v =
|
|
2806
|
+
const v = record[k];
|
|
2410
2807
|
if (v.kind === "Some") _setKey(result, k, v.value);
|
|
2411
2808
|
}
|
|
2412
2809
|
return result;
|
|
@@ -2414,6 +2811,9 @@ const compact = (data) => {
|
|
|
2414
2811
|
/**
|
|
2415
2812
|
* Transforms key and value pairs simultaneously.
|
|
2416
2813
|
*
|
|
2814
|
+
* @see {@link map} for transforming values.
|
|
2815
|
+
* @see {@link mapKeys} for transforming keys.
|
|
2816
|
+
*
|
|
2417
2817
|
* @example
|
|
2418
2818
|
* ```ts
|
|
2419
2819
|
* pipe(
|
|
@@ -2422,13 +2822,13 @@ const compact = (data) => {
|
|
|
2422
2822
|
* ); // { A: 10, B: 20 }
|
|
2423
2823
|
* ```
|
|
2424
2824
|
*/
|
|
2425
|
-
const mapEntries = (
|
|
2426
|
-
const recKeys = Object.keys(
|
|
2825
|
+
const mapEntries = (transform) => (record) => {
|
|
2826
|
+
const recKeys = Object.keys(record);
|
|
2427
2827
|
if (recKeys.length === 0) return {};
|
|
2428
2828
|
const result = {};
|
|
2429
2829
|
for (let i = 0; i < recKeys.length; i++) {
|
|
2430
2830
|
const k = recKeys[i];
|
|
2431
|
-
const [newKey, newVal] =
|
|
2831
|
+
const [newKey, newVal] = transform(k, record[k]);
|
|
2432
2832
|
_setKey(result, newKey, newVal);
|
|
2433
2833
|
}
|
|
2434
2834
|
return result;
|
|
@@ -2444,12 +2844,12 @@ const mapEntries = (f) => (data) => {
|
|
|
2444
2844
|
* ); // { user: { profile: { age: 31 } } }
|
|
2445
2845
|
* ```
|
|
2446
2846
|
*/
|
|
2447
|
-
const updateIn = (path,
|
|
2847
|
+
const updateIn = (path, transform) => (record) => {
|
|
2448
2848
|
const updateNode = (obj, pathKeys) => {
|
|
2449
2849
|
const [head, ...tail] = pathKeys;
|
|
2450
2850
|
if (tail.length === 0) return {
|
|
2451
2851
|
...obj,
|
|
2452
|
-
[head]:
|
|
2852
|
+
[head]: transform(obj?.[head])
|
|
2453
2853
|
};
|
|
2454
2854
|
const child = obj && typeof obj === "object" && head in obj ? obj[head] : {};
|
|
2455
2855
|
return {
|
|
@@ -2457,12 +2857,12 @@ const updateIn = (path, f) => (data) => {
|
|
|
2457
2857
|
[head]: updateNode(child, tail)
|
|
2458
2858
|
};
|
|
2459
2859
|
};
|
|
2460
|
-
return updateNode(
|
|
2860
|
+
return updateNode(record, path);
|
|
2461
2861
|
};
|
|
2462
2862
|
const Rec = {
|
|
2463
2863
|
is: RecIs,
|
|
2464
2864
|
from: RecFrom,
|
|
2465
|
-
to: { Dict: (
|
|
2865
|
+
to: { Dict: (record) => new globalThis.Map(Object.entries(record)) },
|
|
2466
2866
|
map: map$1,
|
|
2467
2867
|
filterMap: filterMap$1,
|
|
2468
2868
|
mapWithKey,
|
|
@@ -2492,13 +2892,13 @@ const Rec = {
|
|
|
2492
2892
|
},
|
|
2493
2893
|
NonEmpty: {
|
|
2494
2894
|
singleton: (key, value) => ({ [key]: value }),
|
|
2495
|
-
from: {
|
|
2496
|
-
keys: (
|
|
2497
|
-
values: (
|
|
2498
|
-
entries: (
|
|
2499
|
-
reduce: (
|
|
2500
|
-
map: (
|
|
2501
|
-
mapWithKey: (
|
|
2895
|
+
from: { record: (record) => _isNonEmpty(record) ? require_Core.Maybe.make.some(record) : require_Core.Maybe.make.none() },
|
|
2896
|
+
keys: (record) => keys(record),
|
|
2897
|
+
values: (record) => values(record),
|
|
2898
|
+
entries: (record) => entries(record),
|
|
2899
|
+
reduce: (reducer) => (record) => values(record).reduce(reducer),
|
|
2900
|
+
map: (transform) => (record) => map$1(transform)(record),
|
|
2901
|
+
mapWithKey: (transform) => (record) => mapWithKey(transform)(record)
|
|
2502
2902
|
}
|
|
2503
2903
|
};
|
|
2504
2904
|
//#endregion
|
|
@@ -2509,18 +2909,21 @@ const StrNonEmptyConst = { from: {
|
|
|
2509
2909
|
*
|
|
2510
2910
|
* @example
|
|
2511
2911
|
* ```ts
|
|
2512
|
-
* Str.NonEmpty.from.
|
|
2513
|
-
* Str.NonEmpty.from.
|
|
2912
|
+
* Str.NonEmpty.from.string("hello"); // Some("hello")
|
|
2913
|
+
* Str.NonEmpty.from.string(""); // None
|
|
2514
2914
|
* ```
|
|
2515
2915
|
*/
|
|
2516
|
-
|
|
2517
|
-
const isEmpty$1 = (
|
|
2518
|
-
const isNonEmpty$1 = (
|
|
2916
|
+
string: (text) => text.length > 0 ? require_Core.Maybe.make.some(text) : require_Core.Maybe.make.none() } };
|
|
2917
|
+
const isEmpty$1 = (text) => text.length === 0;
|
|
2918
|
+
const isNonEmpty$1 = (text) => text.length > 0;
|
|
2919
|
+
const isBlank = (text) => text.trim().length === 0;
|
|
2519
2920
|
const Str = {
|
|
2520
2921
|
is: {
|
|
2521
2922
|
/**
|
|
2522
2923
|
* Returns `true` when the string is empty.
|
|
2523
2924
|
*
|
|
2925
|
+
* @see {@link nonEmpty} for checking if a string contains at least one character.
|
|
2926
|
+
*
|
|
2524
2927
|
* @example
|
|
2525
2928
|
* ```ts
|
|
2526
2929
|
* pipe("", Str.is.empty); // true
|
|
@@ -2530,8 +2933,22 @@ const Str = {
|
|
|
2530
2933
|
empty: isEmpty$1,
|
|
2531
2934
|
/**
|
|
2532
2935
|
* Type guard to check if a string is non-empty.
|
|
2936
|
+
*
|
|
2937
|
+
* @see {@link empty} for checking if a string has zero length.
|
|
2533
2938
|
*/
|
|
2534
|
-
nonEmpty: isNonEmpty$1
|
|
2939
|
+
nonEmpty: isNonEmpty$1,
|
|
2940
|
+
/**
|
|
2941
|
+
* Returns `true` when the string is empty or contains only whitespace.
|
|
2942
|
+
*
|
|
2943
|
+
* @see {@link empty} for checking zero length without trimming whitespace.
|
|
2944
|
+
*
|
|
2945
|
+
* @example
|
|
2946
|
+
* ```ts
|
|
2947
|
+
* pipe(" ", Str.is.blank); // true
|
|
2948
|
+
* pipe("hi", Str.is.blank); // false
|
|
2949
|
+
* ```
|
|
2950
|
+
*/
|
|
2951
|
+
blank: isBlank
|
|
2535
2952
|
},
|
|
2536
2953
|
/**
|
|
2537
2954
|
* Splits a string by a separator. Data-last: use in `pipe`.
|
|
@@ -2541,7 +2958,7 @@ const Str = {
|
|
|
2541
2958
|
* pipe("a,b,c", Str.split(",")); // ["a", "b", "c"]
|
|
2542
2959
|
* ```
|
|
2543
2960
|
*/
|
|
2544
|
-
split: (separator) => (
|
|
2961
|
+
split: (separator) => (text) => text.split(separator),
|
|
2545
2962
|
/**
|
|
2546
2963
|
* Removes leading and trailing whitespace from a string.
|
|
2547
2964
|
*
|
|
@@ -2550,7 +2967,7 @@ const Str = {
|
|
|
2550
2967
|
* pipe(" hello ", Str.trim); // "hello"
|
|
2551
2968
|
* ```
|
|
2552
2969
|
*/
|
|
2553
|
-
trim: (
|
|
2970
|
+
trim: (text) => text.trim(),
|
|
2554
2971
|
/**
|
|
2555
2972
|
* Returns `true` when the string contains the given substring.
|
|
2556
2973
|
*
|
|
@@ -2560,74 +2977,88 @@ const Str = {
|
|
|
2560
2977
|
* pipe("hello world", Str.includes("xyz")); // false
|
|
2561
2978
|
* ```
|
|
2562
2979
|
*/
|
|
2563
|
-
includes: (substring) => (
|
|
2980
|
+
includes: (substring) => (text) => text.includes(substring),
|
|
2564
2981
|
/**
|
|
2565
2982
|
* Replaces the first occurrence of a pattern in a string. Data-last: use in `pipe`.
|
|
2566
2983
|
*
|
|
2984
|
+
* @see {@link replaceAll} for substituting every occurrence instead of only the first.
|
|
2985
|
+
*
|
|
2567
2986
|
* @example
|
|
2568
2987
|
* ```ts
|
|
2569
2988
|
* pipe("foo foo foo", Str.replace("foo", "bar")); // "bar foo foo"
|
|
2570
2989
|
* pipe("Hello World", Str.replace(/world/i, "Earth")); // "Hello Earth"
|
|
2571
2990
|
* ```
|
|
2572
2991
|
*/
|
|
2573
|
-
replace: (pattern, replacement) => (
|
|
2992
|
+
replace: (pattern, replacement) => (text) => text.replace(pattern, replacement),
|
|
2574
2993
|
/**
|
|
2575
2994
|
* Replaces all occurrences of a pattern in a string. Data-last: use in `pipe`.
|
|
2576
2995
|
*
|
|
2996
|
+
* @see {@link replace} for substituting only the first occurrence.
|
|
2997
|
+
*
|
|
2577
2998
|
* @example
|
|
2578
2999
|
* ```ts
|
|
2579
3000
|
* pipe("foo foo foo", Str.replaceAll("foo", "bar")); // "bar bar bar"
|
|
2580
3001
|
* pipe("aAbBaA", Str.replaceAll(/a/gi, "x")); // "xxBBxx"
|
|
2581
3002
|
* ```
|
|
2582
3003
|
*/
|
|
2583
|
-
replaceAll: (pattern, replacement) => (
|
|
3004
|
+
replaceAll: (pattern, replacement) => (text) => text.replaceAll(pattern, replacement),
|
|
2584
3005
|
/**
|
|
2585
3006
|
* Returns `true` when the string starts with the given prefix.
|
|
2586
3007
|
*
|
|
3008
|
+
* @see {@link endsWith} for checking suffix matches.
|
|
3009
|
+
*
|
|
2587
3010
|
* @example
|
|
2588
3011
|
* ```ts
|
|
2589
3012
|
* pipe("hello world", Str.startsWith("hello")); // true
|
|
2590
3013
|
* pipe("hello world", Str.startsWith("world")); // false
|
|
2591
3014
|
* ```
|
|
2592
3015
|
*/
|
|
2593
|
-
startsWith: (prefix) => (
|
|
3016
|
+
startsWith: (prefix) => (text) => text.startsWith(prefix),
|
|
2594
3017
|
/**
|
|
2595
3018
|
* Returns `true` when the string ends with the given suffix.
|
|
2596
3019
|
*
|
|
3020
|
+
* @see {@link startsWith} for checking prefix matches.
|
|
3021
|
+
*
|
|
2597
3022
|
* @example
|
|
2598
3023
|
* ```ts
|
|
2599
3024
|
* pipe("hello world", Str.endsWith("world")); // true
|
|
2600
3025
|
* pipe("hello world", Str.endsWith("hello")); // false
|
|
2601
3026
|
* ```
|
|
2602
3027
|
*/
|
|
2603
|
-
endsWith: (suffix) => (
|
|
3028
|
+
endsWith: (suffix) => (text) => text.endsWith(suffix),
|
|
2604
3029
|
/**
|
|
2605
3030
|
* Converts a string to uppercase.
|
|
2606
3031
|
*
|
|
3032
|
+
* @see {@link toLowerCase} for lowercasing characters.
|
|
3033
|
+
*
|
|
2607
3034
|
* @example
|
|
2608
3035
|
* ```ts
|
|
2609
3036
|
* pipe("hello", Str.toUpperCase); // "HELLO"
|
|
2610
3037
|
* ```
|
|
2611
3038
|
*/
|
|
2612
|
-
toUpperCase: (
|
|
3039
|
+
toUpperCase: (text) => text.toUpperCase(),
|
|
2613
3040
|
/**
|
|
2614
3041
|
* Converts a string to lowercase.
|
|
2615
3042
|
*
|
|
3043
|
+
* @see {@link toUpperCase} for uppercasing characters.
|
|
3044
|
+
*
|
|
2616
3045
|
* @example
|
|
2617
3046
|
* ```ts
|
|
2618
3047
|
* pipe("HELLO", Str.toLowerCase); // "hello"
|
|
2619
3048
|
* ```
|
|
2620
3049
|
*/
|
|
2621
|
-
toLowerCase: (
|
|
3050
|
+
toLowerCase: (text) => text.toLowerCase(),
|
|
2622
3051
|
/**
|
|
2623
3052
|
* Converts the first character of a string to uppercase.
|
|
2624
3053
|
*
|
|
3054
|
+
* @see {@link uncapitalize} for converting the first character to lowercase.
|
|
3055
|
+
*
|
|
2625
3056
|
* @example
|
|
2626
3057
|
* ```ts
|
|
2627
3058
|
* pipe("hello", Str.capitalize); // "Hello"
|
|
2628
3059
|
* ```
|
|
2629
3060
|
*/
|
|
2630
|
-
capitalize: (
|
|
3061
|
+
capitalize: (text) => text.length === 0 ? "" : text.charAt(0).toUpperCase() + text.slice(1),
|
|
2631
3062
|
/**
|
|
2632
3063
|
* Splits a string into lines, normalising `\r\n` and `\r` line endings.
|
|
2633
3064
|
*
|
|
@@ -2637,7 +3068,7 @@ const Str = {
|
|
|
2637
3068
|
* Str.lines("a\r\nb"); // ["a", "b"]
|
|
2638
3069
|
* ```
|
|
2639
3070
|
*/
|
|
2640
|
-
lines: (
|
|
3071
|
+
lines: (text) => text.split(/\r?\n|\r/),
|
|
2641
3072
|
/**
|
|
2642
3073
|
* Splits a string into words on any whitespace boundary, filtering out empty strings.
|
|
2643
3074
|
*
|
|
@@ -2646,17 +3077,7 @@ const Str = {
|
|
|
2646
3077
|
* Str.words(" hello world "); // ["hello", "world"]
|
|
2647
3078
|
* ```
|
|
2648
3079
|
*/
|
|
2649
|
-
words: (
|
|
2650
|
-
/**
|
|
2651
|
-
* Returns `true` when the string is empty or contains only whitespace.
|
|
2652
|
-
*
|
|
2653
|
-
* @example
|
|
2654
|
-
* ```ts
|
|
2655
|
-
* pipe(" ", Str.isBlank); // true
|
|
2656
|
-
* pipe("hi", Str.isBlank); // false
|
|
2657
|
-
* ```
|
|
2658
|
-
*/
|
|
2659
|
-
isBlank: (s) => s.trim().length === 0,
|
|
3080
|
+
words: (text) => text.trim().split(/\s+/).filter(Boolean),
|
|
2660
3081
|
/**
|
|
2661
3082
|
* Returns the length of the string.
|
|
2662
3083
|
*
|
|
@@ -2666,7 +3087,7 @@ const Str = {
|
|
|
2666
3087
|
* pipe("", Str.length); // 0
|
|
2667
3088
|
* ```
|
|
2668
3089
|
*/
|
|
2669
|
-
length: (
|
|
3090
|
+
length: (text) => text.length,
|
|
2670
3091
|
/**
|
|
2671
3092
|
* Extracts a substring between two indices. Data-last: use in `pipe`.
|
|
2672
3093
|
*
|
|
@@ -2676,27 +3097,31 @@ const Str = {
|
|
|
2676
3097
|
* pipe("hello", Str.slice(2)); // "llo"
|
|
2677
3098
|
* ```
|
|
2678
3099
|
*/
|
|
2679
|
-
slice: (start, end) => (
|
|
3100
|
+
slice: (start, end) => (text) => text.slice(start, end),
|
|
2680
3101
|
/**
|
|
2681
3102
|
* Pads the start of a string to a specified length. Data-last: use in `pipe`.
|
|
2682
3103
|
*
|
|
3104
|
+
* @see {@link padEnd} for padding the right side of a string.
|
|
3105
|
+
*
|
|
2683
3106
|
* @example
|
|
2684
3107
|
* ```ts
|
|
2685
3108
|
* pipe("5", Str.padStart(3, "0")); // "005"
|
|
2686
3109
|
* pipe("hi", Str.padStart(5)); // " hi"
|
|
2687
3110
|
* ```
|
|
2688
3111
|
*/
|
|
2689
|
-
padStart: (maxLength, fillString) => (
|
|
3112
|
+
padStart: (maxLength, fillString) => (text) => text.padStart(maxLength, fillString),
|
|
2690
3113
|
/**
|
|
2691
3114
|
* Pads the end of a string to a specified length. Data-last: use in `pipe`.
|
|
2692
3115
|
*
|
|
3116
|
+
* @see {@link padStart} for padding the left side of a string.
|
|
3117
|
+
*
|
|
2693
3118
|
* @example
|
|
2694
3119
|
* ```ts
|
|
2695
3120
|
* pipe("hi", Str.padEnd(5, ".")); // "hi..."
|
|
2696
3121
|
* pipe("hi", Str.padEnd(5)); // "hi "
|
|
2697
3122
|
* ```
|
|
2698
3123
|
*/
|
|
2699
|
-
padEnd: (maxLength, fillString) => (
|
|
3124
|
+
padEnd: (maxLength, fillString) => (text) => text.padEnd(maxLength, fillString),
|
|
2700
3125
|
/**
|
|
2701
3126
|
* Safe number parsers that return `Maybe` instead of `NaN`.
|
|
2702
3127
|
*/
|
|
@@ -2704,6 +3129,8 @@ const Str = {
|
|
|
2704
3129
|
/**
|
|
2705
3130
|
* Parses a string as an integer (base 10). Returns `None` if the result is `NaN`.
|
|
2706
3131
|
*
|
|
3132
|
+
* @see {@link float} for parsing floating-point numbers.
|
|
3133
|
+
*
|
|
2707
3134
|
* @example
|
|
2708
3135
|
* ```ts
|
|
2709
3136
|
* Str.parse.int("42"); // Some(42)
|
|
@@ -2711,14 +3138,16 @@ const Str = {
|
|
|
2711
3138
|
* Str.parse.int("abc"); // None
|
|
2712
3139
|
* ```
|
|
2713
3140
|
*/
|
|
2714
|
-
int: (
|
|
2715
|
-
if (
|
|
2716
|
-
const n = Number.parseInt(
|
|
3141
|
+
int: (text) => {
|
|
3142
|
+
if (text.length === 0) return require_Core.Maybe.make.none();
|
|
3143
|
+
const n = Number.parseInt(text, 10);
|
|
2717
3144
|
return Number.isNaN(n) ? require_Core.Maybe.make.none() : require_Core.Maybe.make.some(n);
|
|
2718
3145
|
},
|
|
2719
3146
|
/**
|
|
2720
3147
|
* Parses a string as a floating-point number. Returns `None` if the result is `NaN`.
|
|
2721
3148
|
*
|
|
3149
|
+
* @see {@link int} for parsing base-10 integers.
|
|
3150
|
+
*
|
|
2722
3151
|
* @example
|
|
2723
3152
|
* ```ts
|
|
2724
3153
|
* Str.parse.float("3.14"); // Some(3.14)
|
|
@@ -2726,38 +3155,57 @@ const Str = {
|
|
|
2726
3155
|
* Str.parse.float("abc"); // None
|
|
2727
3156
|
* ```
|
|
2728
3157
|
*/
|
|
2729
|
-
float: (
|
|
2730
|
-
if (
|
|
2731
|
-
const n = Number.parseFloat(
|
|
3158
|
+
float: (text) => {
|
|
3159
|
+
if (text.length === 0) return require_Core.Maybe.make.none();
|
|
3160
|
+
const n = Number.parseFloat(text);
|
|
2732
3161
|
return Number.isNaN(n) ? require_Core.Maybe.make.none() : require_Core.Maybe.make.some(n);
|
|
2733
3162
|
}
|
|
2734
3163
|
},
|
|
2735
3164
|
/**
|
|
2736
|
-
*
|
|
3165
|
+
* Matches a string against a regular expression.
|
|
3166
|
+
* Pure and safe: resets `pattern.lastIndex = 0` to prevent bugs with stateful `/g` and `/y` regexes.
|
|
3167
|
+
*
|
|
3168
|
+
* @see {@link test} for boolean validation without extracting capture groups.
|
|
2737
3169
|
*
|
|
2738
3170
|
* @example
|
|
2739
3171
|
* ```ts
|
|
2740
|
-
*
|
|
2741
|
-
* Str.
|
|
3172
|
+
* pipe("hello 42", Str.match(/\d+/)); // Some(["42"])
|
|
3173
|
+
* pipe("hello", Str.match(/\d+/)); // None
|
|
2742
3174
|
* ```
|
|
2743
3175
|
*/
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
3176
|
+
match: (pattern) => (text) => {
|
|
3177
|
+
pattern.lastIndex = 0;
|
|
3178
|
+
const result = text.match(pattern);
|
|
3179
|
+
return result !== null ? require_Core.Maybe.make.some(result) : require_Core.Maybe.make.none();
|
|
3180
|
+
},
|
|
3181
|
+
/**
|
|
3182
|
+
* Tests whether a string matches a regular expression.
|
|
3183
|
+
* Pure and safe: resets `pattern.lastIndex = 0` to prevent bugs with stateful `/g` and `/y` regexes.
|
|
3184
|
+
*
|
|
3185
|
+
* @see {@link match} for extracting capture groups into a Maybe.
|
|
3186
|
+
*
|
|
3187
|
+
* @example
|
|
3188
|
+
* ```ts
|
|
3189
|
+
* pipe("user@example.com", Str.test(/^[^@]+@[^@]+$/)); // true
|
|
3190
|
+
* pipe("invalid-email", Str.test(/^[^@]+@[^@]+$/)); // false
|
|
3191
|
+
* ```
|
|
3192
|
+
*/
|
|
3193
|
+
test: (pattern) => (text) => {
|
|
3194
|
+
pattern.lastIndex = 0;
|
|
3195
|
+
return pattern.test(text);
|
|
2750
3196
|
},
|
|
2751
3197
|
/**
|
|
2752
3198
|
* Converts the first character of a string to lower case.
|
|
2753
3199
|
*
|
|
3200
|
+
* @see {@link capitalize} for converting the first character to uppercase.
|
|
3201
|
+
*
|
|
2754
3202
|
* @example
|
|
2755
3203
|
* ```ts
|
|
2756
|
-
*
|
|
2757
|
-
* Str.uncapitalize
|
|
3204
|
+
* pipe("Hello", Str.uncapitalize); // "hello"
|
|
3205
|
+
* pipe("", Str.uncapitalize); // ""
|
|
2758
3206
|
* ```
|
|
2759
3207
|
*/
|
|
2760
|
-
uncapitalize: (
|
|
3208
|
+
uncapitalize: (text) => text.length === 0 ? "" : text.charAt(0).toLowerCase() + text.slice(1),
|
|
2761
3209
|
/**
|
|
2762
3210
|
* Truncates a string to a maximum length, appending an optional suffix (default `"..."`).
|
|
2763
3211
|
* Data-last curried signature.
|
|
@@ -2769,100 +3217,158 @@ const Str = {
|
|
|
2769
3217
|
* pipe("Hello, world!", Str.truncate({ length: 8, suffix: "…" })); // "Hello, w…"
|
|
2770
3218
|
* ```
|
|
2771
3219
|
*/
|
|
2772
|
-
truncate: (options) => (
|
|
3220
|
+
truncate: (options) => (text) => {
|
|
2773
3221
|
const { length: targetLength, suffix = "..." } = options;
|
|
2774
|
-
if (
|
|
3222
|
+
if (text.length <= targetLength) return text;
|
|
2775
3223
|
if (targetLength <= suffix.length) return suffix.slice(0, targetLength);
|
|
2776
|
-
return
|
|
3224
|
+
return text.slice(0, targetLength - suffix.length) + suffix;
|
|
2777
3225
|
},
|
|
2778
3226
|
NonEmpty: StrNonEmptyConst
|
|
2779
3227
|
};
|
|
2780
3228
|
//#endregion
|
|
2781
3229
|
//#region src/Data/Uniq.ts
|
|
2782
|
-
const isEmpty = (
|
|
2783
|
-
const isNonEmpty = (
|
|
3230
|
+
const isEmpty = (set) => set.size === 0;
|
|
3231
|
+
const isNonEmpty = (set) => set.size > 0;
|
|
2784
3232
|
const empty = () => new globalThis.Set();
|
|
2785
3233
|
const singleton = (item) => new globalThis.Set([item]);
|
|
2786
|
-
const fromArray = (
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
3234
|
+
const fromArray = (items) => new globalThis.Set(items);
|
|
3235
|
+
/**
|
|
3236
|
+
* Returns `true` when the set contains the given element.
|
|
3237
|
+
*
|
|
3238
|
+
* @see {@link add} for inserting an element into a set.
|
|
3239
|
+
* @see {@link remove} for deleting an element from a set.
|
|
3240
|
+
*/
|
|
3241
|
+
const has = (item) => (set) => set.has(item);
|
|
3242
|
+
const size = (set) => set.size;
|
|
3243
|
+
/**
|
|
3244
|
+
* Returns a new set with the element added.
|
|
3245
|
+
*
|
|
3246
|
+
* @see {@link remove} for deleting an element from a set.
|
|
3247
|
+
* @see {@link toggle} for toggling presence of an element.
|
|
3248
|
+
*/
|
|
3249
|
+
const add = (item) => (set) => {
|
|
3250
|
+
if (set.has(item)) return set;
|
|
3251
|
+
const result = new globalThis.Set(set);
|
|
2792
3252
|
result.add(item);
|
|
2793
3253
|
return result;
|
|
2794
3254
|
};
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
3255
|
+
/**
|
|
3256
|
+
* Returns a new set with the element removed.
|
|
3257
|
+
*
|
|
3258
|
+
* @see {@link add} for adding an element to a set.
|
|
3259
|
+
*/
|
|
3260
|
+
const remove = (item) => (set) => {
|
|
3261
|
+
if (!set.has(item)) return set;
|
|
3262
|
+
const result = new globalThis.Set(set);
|
|
2798
3263
|
result.delete(item);
|
|
2799
3264
|
return result;
|
|
2800
3265
|
};
|
|
2801
|
-
|
|
2802
|
-
|
|
3266
|
+
/**
|
|
3267
|
+
* Toggles presence of an element in a set.
|
|
3268
|
+
*
|
|
3269
|
+
* @see {@link add} for unconditionally adding an element.
|
|
3270
|
+
* @see {@link remove} for unconditionally removing an element.
|
|
3271
|
+
*/
|
|
3272
|
+
const toggle = (item) => (set) => {
|
|
3273
|
+
const result = new globalThis.Set(set);
|
|
2803
3274
|
if (result.has(item)) result.delete(item);
|
|
2804
3275
|
else result.add(item);
|
|
2805
3276
|
return result;
|
|
2806
3277
|
};
|
|
2807
|
-
|
|
3278
|
+
/**
|
|
3279
|
+
* Transforms each element of a set into a new set.
|
|
3280
|
+
*
|
|
3281
|
+
* @see {@link filterMap} for mapping and filtering in a single step.
|
|
3282
|
+
*/
|
|
3283
|
+
const map = (transform) => (set) => {
|
|
2808
3284
|
const result = new globalThis.Set();
|
|
2809
|
-
for (const item of
|
|
3285
|
+
for (const item of set) result.add(transform(item));
|
|
2810
3286
|
return result;
|
|
2811
3287
|
};
|
|
2812
|
-
|
|
3288
|
+
/**
|
|
3289
|
+
* Filters elements of a set by a predicate.
|
|
3290
|
+
*
|
|
3291
|
+
* @see {@link filterMap} for filtering and mapping simultaneously.
|
|
3292
|
+
*/
|
|
3293
|
+
const filter = (predicate) => (set) => {
|
|
2813
3294
|
const result = new globalThis.Set();
|
|
2814
|
-
for (const item of
|
|
3295
|
+
for (const item of set) if (predicate(item)) result.add(item);
|
|
2815
3296
|
return result;
|
|
2816
3297
|
};
|
|
2817
|
-
|
|
3298
|
+
/**
|
|
3299
|
+
* Transforms elements with a function returning `Maybe`, keeping only `Some` values.
|
|
3300
|
+
*
|
|
3301
|
+
* @see {@link filter} for filtering with a boolean predicate.
|
|
3302
|
+
* @see {@link map} for transforming without filtering.
|
|
3303
|
+
*/
|
|
3304
|
+
const filterMap = (transform) => (set) => {
|
|
2818
3305
|
const result = new globalThis.Set();
|
|
2819
|
-
for (const item of
|
|
2820
|
-
const mb =
|
|
3306
|
+
for (const item of set) {
|
|
3307
|
+
const mb = transform(item);
|
|
2821
3308
|
if (mb.kind === "Some") result.add(mb.value);
|
|
2822
3309
|
}
|
|
2823
3310
|
return result;
|
|
2824
3311
|
};
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
3312
|
+
/**
|
|
3313
|
+
* Computes the union of two sets.
|
|
3314
|
+
*
|
|
3315
|
+
* @see {@link intersection} for keeping only elements present in both sets.
|
|
3316
|
+
* @see {@link difference} for subtracting elements.
|
|
3317
|
+
*/
|
|
3318
|
+
const union = (other) => (set) => {
|
|
3319
|
+
const s = set;
|
|
3320
|
+
if (typeof s.union === "function") return s.union(other);
|
|
3321
|
+
const result = new globalThis.Set(set);
|
|
2829
3322
|
for (const item of other) result.add(item);
|
|
2830
3323
|
return result;
|
|
2831
3324
|
};
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
3325
|
+
/**
|
|
3326
|
+
* Computes the intersection of two sets.
|
|
3327
|
+
*
|
|
3328
|
+
* @see {@link union} for combining elements from both sets.
|
|
3329
|
+
* @see {@link difference} for subtracting elements.
|
|
3330
|
+
*/
|
|
3331
|
+
const intersection = (other) => (set) => {
|
|
3332
|
+
const s = set;
|
|
3333
|
+
if (typeof s.intersection === "function") return s.intersection(other);
|
|
2835
3334
|
const result = new globalThis.Set();
|
|
2836
|
-
for (const item of
|
|
3335
|
+
for (const item of set) if (other.has(item)) result.add(item);
|
|
2837
3336
|
return result;
|
|
2838
3337
|
};
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
3338
|
+
/**
|
|
3339
|
+
* Computes the set difference (`set \ other`).
|
|
3340
|
+
*
|
|
3341
|
+
* @see {@link union} for combining all elements.
|
|
3342
|
+
* @see {@link intersection} for keeping only common elements.
|
|
3343
|
+
*/
|
|
3344
|
+
const difference = (other) => (set) => {
|
|
3345
|
+
const s = set;
|
|
3346
|
+
if (typeof s.difference === "function") return s.difference(other);
|
|
2842
3347
|
const result = new globalThis.Set();
|
|
2843
|
-
for (const item of
|
|
3348
|
+
for (const item of set) if (!other.has(item)) result.add(item);
|
|
2844
3349
|
return result;
|
|
2845
3350
|
};
|
|
2846
|
-
const isSubsetOf = (other) => (
|
|
2847
|
-
const
|
|
2848
|
-
if (typeof
|
|
2849
|
-
for (const item of
|
|
3351
|
+
const isSubsetOf = (other) => (set) => {
|
|
3352
|
+
const s = set;
|
|
3353
|
+
if (typeof s.isSubsetOf === "function") return s.isSubsetOf(other);
|
|
3354
|
+
for (const item of set) if (!other.has(item)) return false;
|
|
2850
3355
|
return true;
|
|
2851
3356
|
};
|
|
2852
|
-
const reduce = (
|
|
2853
|
-
let acc =
|
|
2854
|
-
for (const item of
|
|
3357
|
+
const reduce = (initial, reducer) => (set) => {
|
|
3358
|
+
let acc = initial;
|
|
3359
|
+
for (const item of set) acc = reducer(acc, item);
|
|
2855
3360
|
return acc;
|
|
2856
3361
|
};
|
|
2857
|
-
const toArray = (
|
|
3362
|
+
const toArray = (set) => [...set];
|
|
2858
3363
|
const Uniq = {
|
|
2859
3364
|
is: {
|
|
2860
3365
|
empty: isEmpty,
|
|
2861
|
-
nonEmpty: isNonEmpty
|
|
3366
|
+
nonEmpty: isNonEmpty,
|
|
3367
|
+
subsetOf: isSubsetOf
|
|
2862
3368
|
},
|
|
2863
3369
|
empty,
|
|
2864
3370
|
singleton,
|
|
2865
|
-
from: {
|
|
3371
|
+
from: { array: fromArray },
|
|
2866
3372
|
has,
|
|
2867
3373
|
size,
|
|
2868
3374
|
add,
|
|
@@ -2875,15 +3381,14 @@ const Uniq = {
|
|
|
2875
3381
|
union,
|
|
2876
3382
|
intersection,
|
|
2877
3383
|
difference,
|
|
2878
|
-
isSubsetOf,
|
|
2879
3384
|
reduce,
|
|
2880
|
-
to: {
|
|
3385
|
+
to: { array: toArray },
|
|
2881
3386
|
NonEmpty: {
|
|
2882
3387
|
singleton: (item) => new globalThis.Set([item]),
|
|
2883
|
-
from: {
|
|
2884
|
-
reduce: (
|
|
2885
|
-
map: (
|
|
2886
|
-
to: {
|
|
3388
|
+
from: { set: (set) => set.size > 0 ? require_Core.Maybe.make.some(set) : require_Core.Maybe.make.none() },
|
|
3389
|
+
reduce: (reducer) => (set) => toArray(set).reduce(reducer),
|
|
3390
|
+
map: (transform) => (set) => map(transform)(set),
|
|
3391
|
+
to: { array: (set) => toArray(set) }
|
|
2887
3392
|
}
|
|
2888
3393
|
};
|
|
2889
3394
|
//#endregion
|