@nlozgachev/pipelined 0.10.0 → 0.12.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 +9 -3
- package/esm/src/Core/Option.js +2 -1
- package/esm/src/Core/RemoteData.js +5 -5
- package/esm/src/Core/TaskValidation.js +1 -3
- package/esm/src/Core/Tuple.js +112 -0
- package/esm/src/Core/index.js +4 -5
- package/esm/src/{Core → Utils}/Arr.js +95 -23
- package/esm/src/Utils/Dict.js +421 -0
- package/esm/src/Utils/Num.js +124 -0
- package/esm/src/{Core → Utils}/Rec.js +85 -11
- package/esm/src/Utils/Str.js +134 -0
- package/esm/src/Utils/Uniq.js +265 -0
- package/esm/src/Utils/index.js +6 -0
- package/package.json +11 -1
- package/script/src/Core/Option.js +2 -1
- package/script/src/Core/RemoteData.js +5 -5
- package/script/src/Core/TaskValidation.js +1 -3
- package/script/src/Core/Tuple.js +115 -0
- package/script/src/Core/index.js +4 -5
- package/script/src/{Core → Utils}/Arr.js +95 -23
- package/script/src/Utils/Dict.js +424 -0
- package/script/src/Utils/Num.js +127 -0
- package/script/src/{Core → Utils}/Rec.js +85 -11
- package/script/src/Utils/Str.js +137 -0
- package/script/src/Utils/Uniq.js +268 -0
- package/script/src/Utils/index.js +22 -0
- package/types/src/Composition/compose.d.ts.map +1 -1
- package/types/src/Composition/converge.d.ts.map +1 -1
- package/types/src/Composition/curry.d.ts.map +1 -1
- package/types/src/Composition/flow.d.ts.map +1 -1
- package/types/src/Composition/fn.d.ts.map +1 -1
- package/types/src/Composition/juxt.d.ts.map +1 -1
- package/types/src/Composition/memoize.d.ts.map +1 -1
- package/types/src/Composition/not.d.ts.map +1 -1
- package/types/src/Composition/on.d.ts.map +1 -1
- package/types/src/Composition/pipe.d.ts.map +1 -1
- package/types/src/Composition/uncurry.d.ts.map +1 -1
- package/types/src/Core/Deferred.d.ts.map +1 -1
- package/types/src/Core/Lens.d.ts.map +1 -1
- package/types/src/Core/Logged.d.ts.map +1 -1
- package/types/src/Core/Option.d.ts.map +1 -1
- package/types/src/Core/Optional.d.ts.map +1 -1
- package/types/src/Core/Predicate.d.ts.map +1 -1
- package/types/src/Core/Reader.d.ts.map +1 -1
- package/types/src/Core/Refinement.d.ts.map +1 -1
- package/types/src/Core/RemoteData.d.ts.map +1 -1
- package/types/src/Core/Result.d.ts.map +1 -1
- package/types/src/Core/State.d.ts.map +1 -1
- package/types/src/Core/Task.d.ts.map +1 -1
- package/types/src/Core/TaskOption.d.ts.map +1 -1
- package/types/src/Core/TaskResult.d.ts.map +1 -1
- package/types/src/Core/TaskValidation.d.ts.map +1 -1
- package/types/src/Core/These.d.ts.map +1 -1
- package/types/src/Core/Tuple.d.ts +129 -0
- package/types/src/Core/Tuple.d.ts.map +1 -0
- package/types/src/Core/Validation.d.ts.map +1 -1
- package/types/src/Core/index.d.ts +4 -5
- package/types/src/Core/index.d.ts.map +1 -1
- package/types/src/Types/Brand.d.ts.map +1 -1
- package/types/src/Types/NonEmptyList.d.ts.map +1 -1
- package/types/src/{Core → Utils}/Arr.d.ts +25 -3
- package/types/src/Utils/Arr.d.ts.map +1 -0
- package/types/src/Utils/Dict.d.ts +310 -0
- package/types/src/Utils/Dict.d.ts.map +1 -0
- package/types/src/Utils/Num.d.ts +110 -0
- package/types/src/Utils/Num.d.ts.map +1 -0
- package/types/src/{Core → Utils}/Rec.d.ts +39 -1
- package/types/src/Utils/Rec.d.ts.map +1 -0
- package/types/src/Utils/Str.d.ts +128 -0
- package/types/src/Utils/Str.d.ts.map +1 -0
- package/types/src/Utils/Uniq.d.ts +179 -0
- package/types/src/Utils/Uniq.d.ts.map +1 -0
- package/types/src/Utils/index.d.ts +7 -0
- package/types/src/Utils/index.d.ts.map +1 -0
- package/types/src/Core/Arr.d.ts.map +0 -1
- package/types/src/Core/Rec.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -17,8 +17,6 @@ state flag soup, you get types that name every possible state and make invalid o
|
|
|
17
17
|
Each type comes with a consistent set of operations — `map`, `chain`, `match`, `getOrElse` — that
|
|
18
18
|
compose with `pipe` and `flow`.
|
|
19
19
|
|
|
20
|
-
No FP jargon required. You won't find `Monad`, `Functor`, or `Applicative` in the API.
|
|
21
|
-
|
|
22
20
|
## What's included?
|
|
23
21
|
|
|
24
22
|
### pipelined/core
|
|
@@ -39,8 +37,16 @@ No FP jargon required. You won't find `Monad`, `Functor`, or `Applicative` in th
|
|
|
39
37
|
- **`Optional<S, A>`** — like `Lens`, but the target may be absent (nullable fields, array indices).
|
|
40
38
|
- **`Reader<R, A>`** — a computation that depends on an environment `R`, supplied once at the
|
|
41
39
|
boundary.
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
### pipelined/utils
|
|
43
|
+
|
|
44
|
+
Everyday utilities for built-in JS types.
|
|
45
|
+
|
|
42
46
|
- **`Arr`** — array utilities, data-last, returning `Option` instead of `undefined`.
|
|
43
|
-
- **`Rec`** — record utilities, data-last, with `Option`-returning key lookup.
|
|
47
|
+
- **`Rec`** — record/object utilities, data-last, with `Option`-returning key lookup.
|
|
48
|
+
- **`Num`** — number utilities: `range`, `clamp`, `between`, safe `parse`, and curried arithmetic.
|
|
49
|
+
- **`Str`** — string utilities: `split`, `trim`, `words`, `lines`, and safe `parse.int` / `parse.float`.
|
|
44
50
|
|
|
45
51
|
### pipelined/types
|
|
46
52
|
|
package/esm/src/Core/Option.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Result } from "./Result.js";
|
|
2
|
+
const _none = { kind: "None" };
|
|
2
3
|
export var Option;
|
|
3
4
|
(function (Option) {
|
|
4
5
|
/**
|
|
@@ -12,7 +13,7 @@ export var Option;
|
|
|
12
13
|
/**
|
|
13
14
|
* Creates a None (empty Option).
|
|
14
15
|
*/
|
|
15
|
-
Option.none = () =>
|
|
16
|
+
Option.none = () => _none;
|
|
16
17
|
/**
|
|
17
18
|
* Type guard that checks if a Option is None.
|
|
18
19
|
*/
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { Option } from "./Option.js";
|
|
2
2
|
import { Result } from "./Result.js";
|
|
3
|
+
const _notAsked = { kind: "NotAsked" };
|
|
4
|
+
const _loading = { kind: "Loading" };
|
|
3
5
|
export var RemoteData;
|
|
4
6
|
(function (RemoteData) {
|
|
5
7
|
/**
|
|
6
8
|
* Creates a NotAsked RemoteData.
|
|
7
9
|
*/
|
|
8
|
-
RemoteData.notAsked = () =>
|
|
10
|
+
RemoteData.notAsked = () => _notAsked;
|
|
9
11
|
/**
|
|
10
12
|
* Creates a Loading RemoteData.
|
|
11
13
|
*/
|
|
12
|
-
RemoteData.loading = () =>
|
|
14
|
+
RemoteData.loading = () => _loading;
|
|
13
15
|
/**
|
|
14
16
|
* Creates a Failure RemoteData with the given error.
|
|
15
17
|
*/
|
|
@@ -205,7 +207,5 @@ export var RemoteData;
|
|
|
205
207
|
* ); // Ok(42)
|
|
206
208
|
* ```
|
|
207
209
|
*/
|
|
208
|
-
RemoteData.toResult = (onNotReady) => (data) => RemoteData.isSuccess(data)
|
|
209
|
-
? Result.ok(data.value)
|
|
210
|
-
: Result.err(RemoteData.isFailure(data) ? data.error : onNotReady());
|
|
210
|
+
RemoteData.toResult = (onNotReady) => (data) => RemoteData.isSuccess(data) ? Result.ok(data.value) : Result.err(RemoteData.isFailure(data) ? data.error : onNotReady());
|
|
211
211
|
})(RemoteData || (RemoteData = {}));
|
|
@@ -91,9 +91,7 @@ export var TaskValidation;
|
|
|
91
91
|
* The fallback receives the accumulated error list so callers can inspect which errors occurred.
|
|
92
92
|
* The fallback can produce a different success type, widening the result to `TaskValidation<E, A | B>`.
|
|
93
93
|
*/
|
|
94
|
-
TaskValidation.recover = (fallback) => (data) => Task.chain((validation) => Validation.isValid(validation)
|
|
95
|
-
? Task.resolve(validation)
|
|
96
|
-
: fallback(validation.errors))(data);
|
|
94
|
+
TaskValidation.recover = (fallback) => (data) => Task.chain((validation) => Validation.isValid(validation) ? Task.resolve(validation) : fallback(validation.errors))(data);
|
|
97
95
|
/**
|
|
98
96
|
* Runs two TaskValidations concurrently and combines their results into a tuple.
|
|
99
97
|
* If both are Valid, returns Valid with both values. If either fails, accumulates
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
export var Tuple;
|
|
2
|
+
(function (Tuple) {
|
|
3
|
+
/**
|
|
4
|
+
* Creates a pair from two values.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* Tuple.make("Paris", 2_161_000); // ["Paris", 2161000]
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
Tuple.make = (first, second) => [first, second];
|
|
12
|
+
/**
|
|
13
|
+
* Returns the first value from the pair.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* Tuple.first(Tuple.make("Paris", 2_161_000)); // "Paris"
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
Tuple.first = (tuple) => tuple[0];
|
|
21
|
+
/**
|
|
22
|
+
* Returns the second value from the pair.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* Tuple.second(Tuple.make("Paris", 2_161_000)); // 2161000
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
Tuple.second = (tuple) => tuple[1];
|
|
30
|
+
/**
|
|
31
|
+
* Transforms the first value, leaving the second unchanged.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* pipe(Tuple.make("alice", 42), Tuple.mapFirst((s) => s.toUpperCase())); // ["ALICE", 42]
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
Tuple.mapFirst = (f) => (tuple) => [f(tuple[0]), tuple[1]];
|
|
39
|
+
/**
|
|
40
|
+
* Transforms the second value, leaving the first unchanged.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* pipe(Tuple.make("alice", 42), Tuple.mapSecond((n) => n * 2)); // ["alice", 84]
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
Tuple.mapSecond = (f) => (tuple) => [tuple[0], f(tuple[1])];
|
|
48
|
+
/**
|
|
49
|
+
* Transforms both values independently in a single step.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* pipe(
|
|
54
|
+
* Tuple.make("alice", 42),
|
|
55
|
+
* Tuple.mapBoth(
|
|
56
|
+
* (name) => name.toUpperCase(),
|
|
57
|
+
* (score) => score * 2,
|
|
58
|
+
* ),
|
|
59
|
+
* ); // ["ALICE", 84]
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
Tuple.mapBoth = (onFirst, onSecond) => (tuple) => [
|
|
63
|
+
onFirst(tuple[0]),
|
|
64
|
+
onSecond(tuple[1]),
|
|
65
|
+
];
|
|
66
|
+
/**
|
|
67
|
+
* Applies a binary function to both values, collapsing the pair into a single value.
|
|
68
|
+
* Useful as the final step when consuming a pair in a pipeline.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```ts
|
|
72
|
+
* pipe(Tuple.make("Alice", 100), Tuple.fold((name, score) => `${name}: ${score}`));
|
|
73
|
+
* // "Alice: 100"
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
Tuple.fold = (f) => (tuple) => f(tuple[0], tuple[1]);
|
|
77
|
+
/**
|
|
78
|
+
* Swaps the two values: `[A, B]` becomes `[B, A]`.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* Tuple.swap(Tuple.make("key", 1)); // [1, "key"]
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
Tuple.swap = (tuple) => [tuple[1], tuple[0]];
|
|
86
|
+
/**
|
|
87
|
+
* Converts the pair to a heterogeneous readonly array `readonly (A | B)[]`.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```ts
|
|
91
|
+
* Tuple.toArray(Tuple.make("hello", 42)); // ["hello", 42]
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
Tuple.toArray = (tuple) => [...tuple];
|
|
95
|
+
/**
|
|
96
|
+
* Runs a side effect with both values without changing the pair.
|
|
97
|
+
* Useful for logging or debugging in the middle of a pipeline.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```ts
|
|
101
|
+
* pipe(
|
|
102
|
+
* Tuple.make("Paris", 2_161_000),
|
|
103
|
+
* Tuple.tap((city, pop) => console.log(`${city}: ${pop}`)),
|
|
104
|
+
* Tuple.mapSecond((n) => n / 1_000_000),
|
|
105
|
+
* ); // logs "Paris: 2161000", returns ["Paris", 2.161]
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
Tuple.tap = (f) => (tuple) => {
|
|
109
|
+
f(tuple[0], tuple[1]);
|
|
110
|
+
return tuple;
|
|
111
|
+
};
|
|
112
|
+
})(Tuple || (Tuple = {}));
|
package/esm/src/Core/index.js
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
export * from "./Arr.js";
|
|
2
|
-
export * from "./Logged.js";
|
|
3
1
|
export * from "./Deferred.js";
|
|
4
2
|
export * from "./Lens.js";
|
|
3
|
+
export * from "./Logged.js";
|
|
5
4
|
export * from "./Option.js";
|
|
6
|
-
export * from "./Reader.js";
|
|
7
5
|
export * from "./Optional.js";
|
|
8
|
-
export * from "./Rec.js";
|
|
9
6
|
export * from "./Predicate.js";
|
|
7
|
+
export * from "./Reader.js";
|
|
10
8
|
export * from "./Refinement.js";
|
|
11
9
|
export * from "./RemoteData.js";
|
|
12
|
-
export * from "./State.js";
|
|
13
10
|
export * from "./Result.js";
|
|
11
|
+
export * from "./State.js";
|
|
14
12
|
export * from "./Task.js";
|
|
15
13
|
export * from "./TaskOption.js";
|
|
16
14
|
export * from "./TaskResult.js";
|
|
17
15
|
export * from "./TaskValidation.js";
|
|
18
16
|
export * from "./These.js";
|
|
17
|
+
export * from "./Tuple.js";
|
|
19
18
|
export * from "./Validation.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Deferred } from "
|
|
2
|
-
import { Option } from "
|
|
3
|
-
import { Result } from "
|
|
4
|
-
import { Task } from "
|
|
1
|
+
import { Deferred } from "../Core/Deferred.js";
|
|
2
|
+
import { Option } from "../Core/Option.js";
|
|
3
|
+
import { Result } from "../Core/Result.js";
|
|
4
|
+
import { Task } from "../Core/Task.js";
|
|
5
5
|
import { isNonEmptyList } from "../Types/NonEmptyList.js";
|
|
6
6
|
/**
|
|
7
7
|
* Functional array utilities that compose well with pipe.
|
|
@@ -110,7 +110,13 @@ export var Arr;
|
|
|
110
110
|
* pipe([1, 2, 3], Arr.map(n => n * 2)); // [2, 4, 6]
|
|
111
111
|
* ```
|
|
112
112
|
*/
|
|
113
|
-
Arr.map = (f) => (data) =>
|
|
113
|
+
Arr.map = (f) => (data) => {
|
|
114
|
+
const n = data.length;
|
|
115
|
+
const result = new Array(n);
|
|
116
|
+
for (let i = 0; i < n; i++)
|
|
117
|
+
result[i] = f(data[i]);
|
|
118
|
+
return result;
|
|
119
|
+
};
|
|
114
120
|
/**
|
|
115
121
|
* Filters elements that satisfy the predicate.
|
|
116
122
|
*
|
|
@@ -119,7 +125,15 @@ export var Arr;
|
|
|
119
125
|
* pipe([1, 2, 3, 4], Arr.filter(n => n % 2 === 0)); // [2, 4]
|
|
120
126
|
* ```
|
|
121
127
|
*/
|
|
122
|
-
Arr.filter = (predicate) => (data) =>
|
|
128
|
+
Arr.filter = (predicate) => (data) => {
|
|
129
|
+
const n = data.length;
|
|
130
|
+
const result = [];
|
|
131
|
+
for (let i = 0; i < n; i++) {
|
|
132
|
+
if (predicate(data[i]))
|
|
133
|
+
result.push(data[i]);
|
|
134
|
+
}
|
|
135
|
+
return result;
|
|
136
|
+
};
|
|
123
137
|
/**
|
|
124
138
|
* Splits an array into two groups based on a predicate.
|
|
125
139
|
* First group contains elements that satisfy the predicate,
|
|
@@ -213,9 +227,9 @@ export var Arr;
|
|
|
213
227
|
*/
|
|
214
228
|
Arr.zip = (other) => (data) => {
|
|
215
229
|
const len = Math.min(data.length, other.length);
|
|
216
|
-
const result =
|
|
230
|
+
const result = new Array(len);
|
|
217
231
|
for (let i = 0; i < len; i++) {
|
|
218
|
-
result
|
|
232
|
+
result[i] = [data[i], other[i]];
|
|
219
233
|
}
|
|
220
234
|
return result;
|
|
221
235
|
};
|
|
@@ -229,9 +243,9 @@ export var Arr;
|
|
|
229
243
|
*/
|
|
230
244
|
Arr.zipWith = (f) => (other) => (data) => {
|
|
231
245
|
const len = Math.min(data.length, other.length);
|
|
232
|
-
const result =
|
|
246
|
+
const result = new Array(len);
|
|
233
247
|
for (let i = 0; i < len; i++) {
|
|
234
|
-
result
|
|
248
|
+
result[i] = f(data[i], other[i]);
|
|
235
249
|
}
|
|
236
250
|
return result;
|
|
237
251
|
};
|
|
@@ -286,7 +300,17 @@ export var Arr;
|
|
|
286
300
|
* pipe([1, 2, 3], Arr.flatMap(n => [n, n * 10])); // [1, 10, 2, 20, 3, 30]
|
|
287
301
|
* ```
|
|
288
302
|
*/
|
|
289
|
-
Arr.flatMap = (f) => (data) =>
|
|
303
|
+
Arr.flatMap = (f) => (data) => {
|
|
304
|
+
const n = data.length;
|
|
305
|
+
const result = [];
|
|
306
|
+
for (let i = 0; i < n; i++) {
|
|
307
|
+
const chunk = f(data[i]);
|
|
308
|
+
const m = chunk.length;
|
|
309
|
+
for (let j = 0; j < m; j++)
|
|
310
|
+
result.push(chunk[j]);
|
|
311
|
+
}
|
|
312
|
+
return result;
|
|
313
|
+
};
|
|
290
314
|
/**
|
|
291
315
|
* Reduces an array from the left.
|
|
292
316
|
*
|
|
@@ -313,12 +337,13 @@ export var Arr;
|
|
|
313
337
|
* ```
|
|
314
338
|
*/
|
|
315
339
|
Arr.traverse = (f) => (data) => {
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
340
|
+
const n = data.length;
|
|
341
|
+
const result = new Array(n);
|
|
342
|
+
for (let i = 0; i < n; i++) {
|
|
343
|
+
const mapped = f(data[i]);
|
|
344
|
+
if (mapped.kind === "None")
|
|
320
345
|
return Option.none();
|
|
321
|
-
result
|
|
346
|
+
result[i] = mapped.value;
|
|
322
347
|
}
|
|
323
348
|
return Option.some(result);
|
|
324
349
|
};
|
|
@@ -335,12 +360,13 @@ export var Arr;
|
|
|
335
360
|
* ```
|
|
336
361
|
*/
|
|
337
362
|
Arr.traverseResult = (f) => (data) => {
|
|
338
|
-
const
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
363
|
+
const n = data.length;
|
|
364
|
+
const result = new Array(n);
|
|
365
|
+
for (let i = 0; i < n; i++) {
|
|
366
|
+
const mapped = f(data[i]);
|
|
367
|
+
if (mapped.kind === "Error")
|
|
342
368
|
return mapped;
|
|
343
|
-
result
|
|
369
|
+
result[i] = mapped.value;
|
|
344
370
|
}
|
|
345
371
|
return Result.ok(result);
|
|
346
372
|
};
|
|
@@ -427,7 +453,13 @@ export var Arr;
|
|
|
427
453
|
* pipe([1, 2, 3], Arr.some(n => n > 2)); // true
|
|
428
454
|
* ```
|
|
429
455
|
*/
|
|
430
|
-
Arr.some = (predicate) => (data) =>
|
|
456
|
+
Arr.some = (predicate) => (data) => {
|
|
457
|
+
const n = data.length;
|
|
458
|
+
for (let i = 0; i < n; i++)
|
|
459
|
+
if (predicate(data[i]))
|
|
460
|
+
return true;
|
|
461
|
+
return false;
|
|
462
|
+
};
|
|
431
463
|
/**
|
|
432
464
|
* Returns true if all elements satisfy the predicate.
|
|
433
465
|
*
|
|
@@ -436,7 +468,13 @@ export var Arr;
|
|
|
436
468
|
* pipe([1, 2, 3], Arr.every(n => n > 0)); // true
|
|
437
469
|
* ```
|
|
438
470
|
*/
|
|
439
|
-
Arr.every = (predicate) => (data) =>
|
|
471
|
+
Arr.every = (predicate) => (data) => {
|
|
472
|
+
const n = data.length;
|
|
473
|
+
for (let i = 0; i < n; i++)
|
|
474
|
+
if (!predicate(data[i]))
|
|
475
|
+
return false;
|
|
476
|
+
return true;
|
|
477
|
+
};
|
|
440
478
|
/**
|
|
441
479
|
* Reverses an array. Returns a new array.
|
|
442
480
|
*
|
|
@@ -495,4 +533,38 @@ export var Arr;
|
|
|
495
533
|
i++;
|
|
496
534
|
return data.slice(i);
|
|
497
535
|
};
|
|
536
|
+
/**
|
|
537
|
+
* Like `reduce`, but returns every intermediate accumulator as an array.
|
|
538
|
+
* The initial value is not included — the output has the same length as the input.
|
|
539
|
+
*
|
|
540
|
+
* @example
|
|
541
|
+
* ```ts
|
|
542
|
+
* pipe([1, 2, 3], Arr.scan(0, (acc, n) => acc + n)); // [1, 3, 6]
|
|
543
|
+
* ```
|
|
544
|
+
*/
|
|
545
|
+
Arr.scan = (initial, f) => (data) => {
|
|
546
|
+
const n = data.length;
|
|
547
|
+
const result = new Array(n);
|
|
548
|
+
let acc = initial;
|
|
549
|
+
for (let i = 0; i < n; i++) {
|
|
550
|
+
acc = f(acc, data[i]);
|
|
551
|
+
result[i] = acc;
|
|
552
|
+
}
|
|
553
|
+
return result;
|
|
554
|
+
};
|
|
555
|
+
/**
|
|
556
|
+
* Splits an array at an index into a `[before, after]` tuple.
|
|
557
|
+
* Negative indices clamp to 0; indices beyond the array length clamp to the end.
|
|
558
|
+
*
|
|
559
|
+
* @example
|
|
560
|
+
* ```ts
|
|
561
|
+
* pipe([1, 2, 3, 4], Arr.splitAt(2)); // [[1, 2], [3, 4]]
|
|
562
|
+
* pipe([1, 2, 3], Arr.splitAt(0)); // [[], [1, 2, 3]]
|
|
563
|
+
* pipe([1, 2, 3], Arr.splitAt(10)); // [[1, 2, 3], []]
|
|
564
|
+
* ```
|
|
565
|
+
*/
|
|
566
|
+
Arr.splitAt = (index) => (data) => {
|
|
567
|
+
const i = Math.max(0, index);
|
|
568
|
+
return [data.slice(0, i), data.slice(i)];
|
|
569
|
+
};
|
|
498
570
|
})(Arr || (Arr = {}));
|