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