functionalscript 0.3.10 → 0.3.12
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 +1 -0
- package/bnf/djs/module.f.d.ts +11 -0
- package/bnf/djs/module.f.js +6 -0
- package/bnf/djs/test.f.d.ts +1 -0
- package/bnf/djs/test.f.js +221 -0
- package/bnf/module.f.d.ts +135 -0
- package/bnf/module.f.js +142 -0
- package/bnf/test.f.d.ts +65 -0
- package/bnf/test.f.js +368 -0
- package/crypto/prime_field/module.f.d.ts +1 -4
- package/crypto/secp/module.f.d.ts +2 -2
- package/dev/test/module.f.js +2 -1
- package/fsc/module.f.js +5 -6
- package/fsm/module.f.d.ts +9 -9
- package/fsm/module.f.js +13 -22
- package/html/module.f.js +1 -2
- package/issues/31-json.f.d.ts +1 -0
- package/issues/31-json.f.js +241 -0
- package/js/tokenizer/module.f.js +6 -1
- package/nanvm-lib/tests/test.f.d.ts +4 -0
- package/nanvm-lib/tests/test.f.js +5 -7
- package/nodejs/version/module.f.d.ts +1 -1
- package/package.json +1 -1
- package/text/module.f.js +3 -3
- package/text/utf16/module.f.d.ts +11 -5
- package/text/utf16/module.f.js +2 -0
- package/text/utf16/test.f.js +8 -1
- package/types/btree/find/module.f.d.ts +2 -2
- package/types/btree/remove/module.f.d.ts +4 -4
- package/types/btree/remove/module.f.js +9 -11
- package/types/btree/remove/test.f.js +2 -2
- package/types/btree/set/module.f.d.ts +3 -3
- package/types/byte_set/test.f.js +31 -31
- package/types/function/module.f.d.ts +1 -1
- package/types/range_map/module.f.d.ts +79 -2
- package/types/range_map/module.f.js +49 -2
- package/types/range_map/test.f.d.ts +1 -0
- package/types/range_map/test.f.js +76 -33
- package/types/result/module.f.d.ts +48 -1
- package/types/result/module.f.js +40 -2
- package/types/result/test.f.d.ts +4 -0
- package/types/result/test.f.js +18 -0
- package/types/sorted_list/module.f.js +8 -7
- package/types/sorted_set/module.f.d.ts +28 -0
- package/types/sorted_set/test.f.d.ts +1 -0
- package/types/sorted_set/test.f.js +19 -0
- package/types/string/module.f.d.ts +17 -0
- package/types/string/module.f.js +17 -0
- package/types/string/test.f.d.ts +1 -0
- package/types/string/test.f.js +15 -0
- package/types/string_set/module.f.d.ts +21 -0
- package/types/string_set/module.f.js +21 -0
- package/types/string_set/test.f.d.ts +1 -0
- package/types/string_set/test.f.js +18 -1
|
@@ -1,14 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions and types for managing and merging range maps.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
*
|
|
8
|
+
* ```js
|
|
9
|
+
* const rmOps = rangeMap({
|
|
10
|
+
* union: a => b => a | b,
|
|
11
|
+
* equal: a => b => a === b,
|
|
12
|
+
* def: 0,
|
|
13
|
+
* })
|
|
14
|
+
*
|
|
15
|
+
* // Create range maps
|
|
16
|
+
* const range1 = rmOps.fromRange([0, 10])(2)
|
|
17
|
+
* const range2 = rmOps.fromRange([5, 15])(5)
|
|
18
|
+
*
|
|
19
|
+
* // Merge range maps
|
|
20
|
+
* const merged = toArray(rmOps.merge(range1)(range2))
|
|
21
|
+
*
|
|
22
|
+
* // Retrieve values from the merged range map
|
|
23
|
+
* //
|
|
24
|
+
* if (rmOps.get(-1)(merged) !== 0) { throw 'error' }
|
|
25
|
+
* //
|
|
26
|
+
* if (rmOps.get(0)(merged) !== 2) { throw 'error' }
|
|
27
|
+
* if (rmOps.get(2)(merged) !== 2) { throw 'error' }
|
|
28
|
+
* // overlapped: 2 | 5 = 7
|
|
29
|
+
* if (rmOps.get(7)(merged) !== 7) { throw 'error' }
|
|
30
|
+
* //
|
|
31
|
+
* if (rmOps.get(12)(merged) !== 5) { throw 'error' }
|
|
32
|
+
* if (rmOps.get(15)(merged) !== 5) { throw 'error' }
|
|
33
|
+
* //
|
|
34
|
+
* if (rmOps.get(16)(merged) !== 0) { throw 'error' }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
1
37
|
import { type SortedList } from '../sorted_list/module.f.ts';
|
|
2
38
|
import type { Reduce, Equal } from '../function/operator/module.f.ts';
|
|
3
39
|
import type { Range } from '../range/module.f.ts';
|
|
4
40
|
export type Entry<T> = [T, number];
|
|
41
|
+
/**
|
|
42
|
+
* A sorted list of entries, where each entry is a tuple `[T, number]` that maps a value of type `T` to an upper boundary
|
|
43
|
+
* of a numeric range.
|
|
44
|
+
*/
|
|
5
45
|
export type RangeMap<T> = SortedList<Entry<T>>;
|
|
6
46
|
export type RangeMapArray<T> = readonly Entry<T>[];
|
|
7
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Defines the properties and operations required for managing range maps.
|
|
49
|
+
*/
|
|
50
|
+
export type Properties<T> = {
|
|
51
|
+
/**
|
|
52
|
+
* A function to merge two values of type `T`. This defines how overlapping ranges are combined.
|
|
53
|
+
*/
|
|
8
54
|
readonly union: Reduce<T>;
|
|
55
|
+
/**
|
|
56
|
+
* A function to check equality between two values of type `T`.
|
|
57
|
+
*/
|
|
9
58
|
readonly equal: Equal<T>;
|
|
59
|
+
/**
|
|
60
|
+
* The default value used when no range matches or for initializing ranges.
|
|
61
|
+
*/
|
|
62
|
+
readonly def: T;
|
|
10
63
|
};
|
|
11
64
|
export type RangeMerge<T> = Reduce<RangeMap<T>>;
|
|
12
|
-
export declare const merge: <T>(op:
|
|
65
|
+
export declare const merge: <T>(op: Properties<T>) => RangeMerge<T>;
|
|
13
66
|
export declare const get: <T>(def: T) => (value: number) => (rm: RangeMapArray<T>) => T;
|
|
14
67
|
export declare const fromRange: <T>(def: T) => (r: Range) => (value: T) => RangeMapArray<T>;
|
|
68
|
+
/**
|
|
69
|
+
* Represents a set of operations for managing range maps.
|
|
70
|
+
*/
|
|
71
|
+
export type RangeMapOp<T> = {
|
|
72
|
+
/**
|
|
73
|
+
* Merges two range maps into a single range map.
|
|
74
|
+
*/
|
|
75
|
+
readonly merge: RangeMerge<T>;
|
|
76
|
+
/**
|
|
77
|
+
* Retrieves the value associated with a given numeric range.
|
|
78
|
+
*/
|
|
79
|
+
readonly get: (value: number) => (rm: RangeMapArray<T>) => T;
|
|
80
|
+
/**
|
|
81
|
+
* Constructs a range map for a single numeric range and value.
|
|
82
|
+
*/
|
|
83
|
+
readonly fromRange: (r: Range) => (value: T) => RangeMapArray<T>;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Creates a set of operations for managing range maps using the specified properties.
|
|
87
|
+
*
|
|
88
|
+
* @param op - The properties defining union and equality operations and the default value.
|
|
89
|
+
* @returns An object containing operations for merging, retrieving, and constructing range maps.
|
|
90
|
+
*/
|
|
91
|
+
export declare const rangeMap: <T>(op: Properties<T>) => RangeMapOp<T>;
|
|
@@ -1,7 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions and types for managing and merging range maps.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
*
|
|
8
|
+
* ```js
|
|
9
|
+
* const rmOps = rangeMap({
|
|
10
|
+
* union: a => b => a | b,
|
|
11
|
+
* equal: a => b => a === b,
|
|
12
|
+
* def: 0,
|
|
13
|
+
* })
|
|
14
|
+
*
|
|
15
|
+
* // Create range maps
|
|
16
|
+
* const range1 = rmOps.fromRange([0, 10])(2)
|
|
17
|
+
* const range2 = rmOps.fromRange([5, 15])(5)
|
|
18
|
+
*
|
|
19
|
+
* // Merge range maps
|
|
20
|
+
* const merged = toArray(rmOps.merge(range1)(range2))
|
|
21
|
+
*
|
|
22
|
+
* // Retrieve values from the merged range map
|
|
23
|
+
* //
|
|
24
|
+
* if (rmOps.get(-1)(merged) !== 0) { throw 'error' }
|
|
25
|
+
* //
|
|
26
|
+
* if (rmOps.get(0)(merged) !== 2) { throw 'error' }
|
|
27
|
+
* if (rmOps.get(2)(merged) !== 2) { throw 'error' }
|
|
28
|
+
* // overlapped: 2 | 5 = 7
|
|
29
|
+
* if (rmOps.get(7)(merged) !== 7) { throw 'error' }
|
|
30
|
+
* //
|
|
31
|
+
* if (rmOps.get(12)(merged) !== 5) { throw 'error' }
|
|
32
|
+
* if (rmOps.get(15)(merged) !== 5) { throw 'error' }
|
|
33
|
+
* //
|
|
34
|
+
* if (rmOps.get(16)(merged) !== 0) { throw 'error' }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
1
37
|
import { genericMerge } from "../sorted_list/module.f.js";
|
|
2
38
|
import { next } from "../list/module.f.js";
|
|
3
39
|
import { cmp } from "../number/module.f.js";
|
|
4
|
-
const reduceOp = union
|
|
40
|
+
const reduceOp = ({ union, equal }) => state => ([aItem, aMax]) => ([bItem, bMax]) => {
|
|
5
41
|
const sign = cmp(aMax)(bMax);
|
|
6
42
|
const min = sign === 1 ? bMax : aMax;
|
|
7
43
|
const u = union(aItem)(bItem);
|
|
@@ -21,7 +57,7 @@ const tailReduce = equal => state => tail => {
|
|
|
21
57
|
}
|
|
22
58
|
return { first: state, tail: tailResult };
|
|
23
59
|
};
|
|
24
|
-
export const merge =
|
|
60
|
+
export const merge = op => genericMerge({ reduceOp: reduceOp(op), tailReduce: tailReduce(op.equal) })(null);
|
|
25
61
|
export const get = def => value => rm => {
|
|
26
62
|
const len = rm.length;
|
|
27
63
|
let b = 0;
|
|
@@ -43,3 +79,14 @@ export const get = def => value => rm => {
|
|
|
43
79
|
}
|
|
44
80
|
};
|
|
45
81
|
export const fromRange = def => ([a, b]) => v => [[def, a - 1], [v, b]];
|
|
82
|
+
/**
|
|
83
|
+
* Creates a set of operations for managing range maps using the specified properties.
|
|
84
|
+
*
|
|
85
|
+
* @param op - The properties defining union and equality operations and the default value.
|
|
86
|
+
* @returns An object containing operations for merging, retrieving, and constructing range maps.
|
|
87
|
+
*/
|
|
88
|
+
export const rangeMap = (op) => ({
|
|
89
|
+
merge: merge(op),
|
|
90
|
+
get: get(op.def),
|
|
91
|
+
fromRange: fromRange(op.def),
|
|
92
|
+
});
|
|
@@ -1,19 +1,62 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { get, merge, fromRange, rangeMap } from "./module.f.js";
|
|
2
2
|
import { unsafeCmp } from "../function/compare/module.f.js";
|
|
3
3
|
import * as json from "../../json/module.f.js";
|
|
4
4
|
import { sort } from "../object/module.f.js";
|
|
5
|
-
import
|
|
6
|
-
import
|
|
5
|
+
import { union } from "../sorted_set/module.f.js";
|
|
6
|
+
import { equal, toArray } from "../list/module.f.js";
|
|
7
7
|
import * as operator from "../function/operator/module.f.js";
|
|
8
8
|
const stringify = json.stringify(sort);
|
|
9
|
-
const op = {
|
|
9
|
+
const op = {
|
|
10
|
+
union: union(unsafeCmp),
|
|
11
|
+
equal: equal(operator.strictEqual),
|
|
12
|
+
def: []
|
|
13
|
+
};
|
|
10
14
|
export default {
|
|
15
|
+
example: () => {
|
|
16
|
+
const rmOps = rangeMap({
|
|
17
|
+
union: a => b => a | b,
|
|
18
|
+
equal: a => b => a === b,
|
|
19
|
+
def: 0,
|
|
20
|
+
});
|
|
21
|
+
// Create range maps
|
|
22
|
+
const range1 = rmOps.fromRange([0, 10])(2);
|
|
23
|
+
const range2 = rmOps.fromRange([5, 15])(5);
|
|
24
|
+
// Merge range maps
|
|
25
|
+
const merged = toArray(rmOps.merge(range1)(range2));
|
|
26
|
+
// Retrieve values from the merged range map
|
|
27
|
+
//
|
|
28
|
+
if (rmOps.get(-1)(merged) !== 0) {
|
|
29
|
+
throw 'error';
|
|
30
|
+
}
|
|
31
|
+
//
|
|
32
|
+
if (rmOps.get(0)(merged) !== 2) {
|
|
33
|
+
throw 'error';
|
|
34
|
+
}
|
|
35
|
+
if (rmOps.get(2)(merged) !== 2) {
|
|
36
|
+
throw 'error';
|
|
37
|
+
}
|
|
38
|
+
// 2 | 5 = 7
|
|
39
|
+
if (rmOps.get(7)(merged) !== 7) {
|
|
40
|
+
throw 'error';
|
|
41
|
+
}
|
|
42
|
+
//
|
|
43
|
+
if (rmOps.get(12)(merged) !== 5) {
|
|
44
|
+
throw 'error';
|
|
45
|
+
}
|
|
46
|
+
if (rmOps.get(15)(merged) !== 5) {
|
|
47
|
+
throw 'error';
|
|
48
|
+
}
|
|
49
|
+
//
|
|
50
|
+
if (rmOps.get(16)(merged) !== 0) {
|
|
51
|
+
throw 'error';
|
|
52
|
+
}
|
|
53
|
+
},
|
|
11
54
|
merge: [
|
|
12
55
|
() => {
|
|
13
56
|
const a = [[['a'], 1], [['b'], 2]];
|
|
14
57
|
const b = null;
|
|
15
|
-
const merged =
|
|
16
|
-
const result = stringify(
|
|
58
|
+
const merged = merge(op)(a)(b);
|
|
59
|
+
const result = stringify(toArray(merged));
|
|
17
60
|
if (result !== '[[["a"],1],[["b"],2]]') {
|
|
18
61
|
throw result;
|
|
19
62
|
}
|
|
@@ -21,8 +64,8 @@ export default {
|
|
|
21
64
|
() => {
|
|
22
65
|
const a = null;
|
|
23
66
|
const b = [[['a'], 1], [['b'], 2]];
|
|
24
|
-
const merged =
|
|
25
|
-
const result = stringify(
|
|
67
|
+
const merged = merge(op)(a)(b);
|
|
68
|
+
const result = stringify(toArray(merged));
|
|
26
69
|
if (result !== '[[["a"],1],[["b"],2]]') {
|
|
27
70
|
throw result;
|
|
28
71
|
}
|
|
@@ -30,8 +73,8 @@ export default {
|
|
|
30
73
|
() => {
|
|
31
74
|
const a = [[['a'], 1], [['b'], 2]];
|
|
32
75
|
const b = [[['a'], 1], [['b'], 2]];
|
|
33
|
-
const merged =
|
|
34
|
-
const result = stringify(
|
|
76
|
+
const merged = merge(op)(a)(b);
|
|
77
|
+
const result = stringify(toArray(merged));
|
|
35
78
|
if (result !== '[[["a"],1],[["b"],2]]') {
|
|
36
79
|
throw result;
|
|
37
80
|
}
|
|
@@ -39,8 +82,8 @@ export default {
|
|
|
39
82
|
() => {
|
|
40
83
|
const a = [[['a'], 1], [['c'], 3]];
|
|
41
84
|
const b = [[['b'], 2], [['d'], 4]];
|
|
42
|
-
const merged =
|
|
43
|
-
const result = stringify(
|
|
85
|
+
const merged = merge(op)(a)(b);
|
|
86
|
+
const result = stringify(toArray(merged));
|
|
44
87
|
if (result !== '[[["a","b"],1],[["b","c"],2],[["c","d"],3],[["d"],4]]') {
|
|
45
88
|
throw result;
|
|
46
89
|
}
|
|
@@ -48,8 +91,8 @@ export default {
|
|
|
48
91
|
() => {
|
|
49
92
|
const a = [[['a'], 1], [['d'], 4]];
|
|
50
93
|
const b = [[['b'], 2], [['c'], 3]];
|
|
51
|
-
const merged =
|
|
52
|
-
const result = stringify(
|
|
94
|
+
const merged = merge(op)(a)(b);
|
|
95
|
+
const result = stringify(toArray(merged));
|
|
53
96
|
if (result !== '[[["a","b"],1],[["b","d"],2],[["c","d"],3],[["d"],4]]') {
|
|
54
97
|
throw result;
|
|
55
98
|
}
|
|
@@ -57,8 +100,8 @@ export default {
|
|
|
57
100
|
() => {
|
|
58
101
|
const a = [[['a'], 1], [['b'], 2]];
|
|
59
102
|
const b = [[['b'], 1], [['a'], 2]];
|
|
60
|
-
const merged =
|
|
61
|
-
const result = stringify(
|
|
103
|
+
const merged = merge(op)(a)(b);
|
|
104
|
+
const result = stringify(toArray(merged));
|
|
62
105
|
if (result !== '[[["a","b"],2]]') {
|
|
63
106
|
throw result;
|
|
64
107
|
}
|
|
@@ -66,8 +109,8 @@ export default {
|
|
|
66
109
|
() => {
|
|
67
110
|
const a = [[['a'], 1], [['b'], 2], [['a'], 3]];
|
|
68
111
|
const b = [[['a'], 5]];
|
|
69
|
-
const merged =
|
|
70
|
-
const result = stringify(
|
|
112
|
+
const merged = merge(op)(a)(b);
|
|
113
|
+
const result = stringify(toArray(merged));
|
|
71
114
|
if (result !== '[[["a"],1],[["a","b"],2],[["a"],5]]') {
|
|
72
115
|
throw result;
|
|
73
116
|
}
|
|
@@ -75,60 +118,60 @@ export default {
|
|
|
75
118
|
],
|
|
76
119
|
get: () => {
|
|
77
120
|
const sortedSetEmpty = [];
|
|
78
|
-
const
|
|
121
|
+
const at = get(sortedSetEmpty);
|
|
79
122
|
return [
|
|
80
123
|
() => {
|
|
81
124
|
const rm = [[['a'], 10], [['b'], 20], [['c'], 30]];
|
|
82
|
-
const result = stringify(
|
|
125
|
+
const result = stringify(at(5)(rm));
|
|
83
126
|
if (result !== '["a"]') {
|
|
84
127
|
throw result;
|
|
85
128
|
}
|
|
86
129
|
},
|
|
87
130
|
() => {
|
|
88
131
|
const rm = [[['a'], 10], [['b'], 20], [['c'], 30]];
|
|
89
|
-
const result = stringify(
|
|
132
|
+
const result = stringify(at(10)(rm));
|
|
90
133
|
if (result !== '["a"]') {
|
|
91
134
|
throw result;
|
|
92
135
|
}
|
|
93
136
|
},
|
|
94
137
|
() => {
|
|
95
138
|
const rm = [[['a'], 10], [['b'], 20], [['c'], 30]];
|
|
96
|
-
const result = stringify(
|
|
139
|
+
const result = stringify(at(15)(rm));
|
|
97
140
|
if (result !== '["b"]') {
|
|
98
141
|
throw result;
|
|
99
142
|
}
|
|
100
143
|
},
|
|
101
144
|
() => {
|
|
102
145
|
const rm = [[['a'], 10], [['b'], 20], [['c'], 30]];
|
|
103
|
-
const result = stringify(
|
|
146
|
+
const result = stringify(at(20)(rm));
|
|
104
147
|
if (result !== '["b"]') {
|
|
105
148
|
throw result;
|
|
106
149
|
}
|
|
107
150
|
},
|
|
108
151
|
() => {
|
|
109
152
|
const rm = [[['a'], 10], [['b'], 20], [['c'], 30]];
|
|
110
|
-
const result = stringify(
|
|
153
|
+
const result = stringify(at(25)(rm));
|
|
111
154
|
if (result !== '["c"]') {
|
|
112
155
|
throw result;
|
|
113
156
|
}
|
|
114
157
|
},
|
|
115
158
|
() => {
|
|
116
159
|
const rm = [[['a'], 10], [['b'], 20], [['c'], 30]];
|
|
117
|
-
const result = stringify(
|
|
160
|
+
const result = stringify(at(30)(rm));
|
|
118
161
|
if (result !== '["c"]') {
|
|
119
162
|
throw result;
|
|
120
163
|
}
|
|
121
164
|
},
|
|
122
165
|
() => {
|
|
123
166
|
const rm = [[['a'], 10], [['b'], 20], [['c'], 30]];
|
|
124
|
-
const result = stringify(
|
|
167
|
+
const result = stringify(at(35)(rm));
|
|
125
168
|
if (result !== '[]') {
|
|
126
169
|
throw result;
|
|
127
170
|
}
|
|
128
171
|
},
|
|
129
172
|
() => {
|
|
130
173
|
const rm = [];
|
|
131
|
-
const result = stringify(
|
|
174
|
+
const result = stringify(at(10)(rm));
|
|
132
175
|
if (result !== '[]') {
|
|
133
176
|
throw result;
|
|
134
177
|
}
|
|
@@ -137,34 +180,34 @@ export default {
|
|
|
137
180
|
},
|
|
138
181
|
fromRange: () => {
|
|
139
182
|
const def = -1;
|
|
140
|
-
const rm =
|
|
183
|
+
const rm = fromRange(def)([1, 7])(42);
|
|
141
184
|
return [
|
|
142
185
|
() => {
|
|
143
|
-
const result =
|
|
186
|
+
const result = get(def)(0)(rm);
|
|
144
187
|
if (result !== -1) {
|
|
145
188
|
throw result;
|
|
146
189
|
}
|
|
147
190
|
},
|
|
148
191
|
() => {
|
|
149
|
-
const result =
|
|
192
|
+
const result = get(def)(1)(rm);
|
|
150
193
|
if (result !== 42) {
|
|
151
194
|
throw result;
|
|
152
195
|
}
|
|
153
196
|
},
|
|
154
197
|
() => {
|
|
155
|
-
const result =
|
|
198
|
+
const result = get(def)(3)(rm);
|
|
156
199
|
if (result !== 42) {
|
|
157
200
|
throw result;
|
|
158
201
|
}
|
|
159
202
|
},
|
|
160
203
|
() => {
|
|
161
|
-
const result =
|
|
204
|
+
const result = get(def)(7)(rm);
|
|
162
205
|
if (result !== 42) {
|
|
163
206
|
throw result;
|
|
164
207
|
}
|
|
165
208
|
},
|
|
166
209
|
() => {
|
|
167
|
-
const result =
|
|
210
|
+
const result = get(def)(9)(rm);
|
|
168
211
|
if (result !== -1) {
|
|
169
212
|
throw result;
|
|
170
213
|
}
|
|
@@ -1,6 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A module for representing and handling operations that can succeed or fail.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { error, ok, unwrap, type Result } from './module.f.ts'
|
|
10
|
+
*
|
|
11
|
+
* const success: Result<number, string> = ok(42)
|
|
12
|
+
* const failure: Result<number, string> = error('Something went wrong')
|
|
13
|
+
*
|
|
14
|
+
* if (unwrap(success) !== 42) { throw 'error' }
|
|
15
|
+
* const [kind, v] = failure
|
|
16
|
+
* if (kind !== 'error') { throw 'error' }
|
|
17
|
+
* // `v` is inferred as `string` here
|
|
18
|
+
* if (v !== 'Something went wrong') { throw 'error' }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Represents a successful result.
|
|
23
|
+
*/
|
|
1
24
|
export type Ok<T> = readonly ['ok', T];
|
|
25
|
+
/**
|
|
26
|
+
* Represents a failed result.
|
|
27
|
+
*/
|
|
2
28
|
export type Error<E> = readonly ['error', E];
|
|
29
|
+
/**
|
|
30
|
+
* Represents a result that can be either successful or failed.
|
|
31
|
+
*/
|
|
3
32
|
export type Result<T, E> = Ok<T> | Error<E>;
|
|
33
|
+
/**
|
|
34
|
+
* Creates a successful result.
|
|
35
|
+
*
|
|
36
|
+
* @param value - The value to wrap.
|
|
37
|
+
* @returns A successful result containing the value.
|
|
38
|
+
*/
|
|
4
39
|
export declare const ok: <T>(value: T) => Ok<T>;
|
|
40
|
+
/**
|
|
41
|
+
* Creates a failed result.
|
|
42
|
+
*
|
|
43
|
+
* @param e - The error to wrap.
|
|
44
|
+
* @returns A failed result containing the error.
|
|
45
|
+
*/
|
|
5
46
|
export declare const error: <E>(e: E) => Error<E>;
|
|
6
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Unwraps a result, returning the value if successful or throwing the error if failed.
|
|
49
|
+
*
|
|
50
|
+
* @param param0 - The result to unwrap.
|
|
51
|
+
* @returns The value if the result is successful. Otherwise, throws the error.
|
|
52
|
+
*/
|
|
53
|
+
export declare const unwrap: <T, E>([kind, v]: Result<T, E>) => T;
|
package/types/result/module.f.js
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* A module for representing and handling operations that can succeed or fail.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { error, ok, unwrap, type Result } from './module.f.ts'
|
|
10
|
+
*
|
|
11
|
+
* const success: Result<number, string> = ok(42)
|
|
12
|
+
* const failure: Result<number, string> = error('Something went wrong')
|
|
13
|
+
*
|
|
14
|
+
* if (unwrap(success) !== 42) { throw 'error' }
|
|
15
|
+
* const [kind, v] = failure
|
|
16
|
+
* if (kind !== 'error') { throw 'error' }
|
|
17
|
+
* // `v` is inferred as `string` here
|
|
18
|
+
* if (v !== 'Something went wrong') { throw 'error' }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Creates a successful result.
|
|
23
|
+
*
|
|
24
|
+
* @param value - The value to wrap.
|
|
25
|
+
* @returns A successful result containing the value.
|
|
26
|
+
*/
|
|
27
|
+
export const ok = (value) => ['ok', value];
|
|
28
|
+
/**
|
|
29
|
+
* Creates a failed result.
|
|
30
|
+
*
|
|
31
|
+
* @param e - The error to wrap.
|
|
32
|
+
* @returns A failed result containing the error.
|
|
33
|
+
*/
|
|
34
|
+
export const error = (e) => ['error', e];
|
|
35
|
+
/**
|
|
36
|
+
* Unwraps a result, returning the value if successful or throwing the error if failed.
|
|
37
|
+
*
|
|
38
|
+
* @param param0 - The result to unwrap.
|
|
39
|
+
* @returns The value if the result is successful. Otherwise, throws the error.
|
|
40
|
+
*/
|
|
3
41
|
export const unwrap = ([kind, v]) => {
|
|
4
42
|
if (kind === 'error') {
|
|
5
43
|
throw v;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { error, ok, unwrap } from "./module.f.js";
|
|
2
|
+
export default {
|
|
3
|
+
example: () => {
|
|
4
|
+
const success = ok(42);
|
|
5
|
+
const failure = error('Something went wrong');
|
|
6
|
+
if (unwrap(success) !== 42) {
|
|
7
|
+
throw 'error';
|
|
8
|
+
}
|
|
9
|
+
const [kind, v] = failure;
|
|
10
|
+
if (kind !== 'error') {
|
|
11
|
+
throw 'error';
|
|
12
|
+
}
|
|
13
|
+
// `v` is inferred as `string` here
|
|
14
|
+
if (v !== 'Something went wrong') {
|
|
15
|
+
throw 'error';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { next } from "../list/module.f.js";
|
|
2
2
|
import { identity } from "../function/module.f.js";
|
|
3
3
|
export const genericMerge = ({ reduceOp, tailReduce }) => {
|
|
4
|
-
const f = state => a => b => () => {
|
|
4
|
+
const f = (state) => (a) => (b) => () => {
|
|
5
5
|
const aResult = next(a);
|
|
6
6
|
if (aResult === null) {
|
|
7
7
|
return tailReduce(state)(b);
|
|
@@ -22,20 +22,21 @@ export const merge = (cmp) => {
|
|
|
22
22
|
const tailReduce = mergeTail;
|
|
23
23
|
return genericMerge({ reduceOp: cmpReduce(cmp), tailReduce })(null);
|
|
24
24
|
};
|
|
25
|
-
const cmpReduce = cmp => () => a => b => {
|
|
25
|
+
const cmpReduce = (cmp) => () => a => b => {
|
|
26
26
|
const sign = cmp(a)(b);
|
|
27
27
|
return [sign === 1 ? b : a, sign, null];
|
|
28
28
|
};
|
|
29
29
|
const mergeTail = () => identity;
|
|
30
|
-
export const find = cmp => value => array => {
|
|
30
|
+
export const find = (cmp) => (value) => (array) => {
|
|
31
|
+
const cmpValue = cmp(value);
|
|
31
32
|
let b = 0;
|
|
32
33
|
let e = array.length - 1;
|
|
33
34
|
while (true) {
|
|
34
|
-
|
|
35
|
+
const d = e - b;
|
|
36
|
+
if (d < 0)
|
|
35
37
|
return null;
|
|
36
|
-
const mid = b + (
|
|
37
|
-
|
|
38
|
-
switch (sign) {
|
|
38
|
+
const mid = b + (d >> 1);
|
|
39
|
+
switch (cmpValue(array[mid])) {
|
|
39
40
|
case -1: {
|
|
40
41
|
e = mid - 1;
|
|
41
42
|
break;
|
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A sorted set, implemented as a sorted array.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*
|
|
6
|
+
* @note
|
|
7
|
+
*
|
|
8
|
+
* All input arrays must be pre-sorted according to the provided comparison function (`Cmp<T>`).
|
|
9
|
+
* The correctness of these functions depend on this requirement.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
*
|
|
13
|
+
* ```js
|
|
14
|
+
* import { union, intersect, has } from './module.f.ts'
|
|
15
|
+
*
|
|
16
|
+
* const cmp = (a: number) => (b: number) => a < b ? -1 : a > b ? 1 : 0
|
|
17
|
+
*
|
|
18
|
+
* const setA = [1, 3, 5]
|
|
19
|
+
* const setB = [3, 4, 5]
|
|
20
|
+
*
|
|
21
|
+
* const unionSet = union(cmp)(setA)(setB) // [1, 3, 4, 5]
|
|
22
|
+
*
|
|
23
|
+
* const intersectionSet = intersect(cmp)(setA)(setB) // [3, 5]
|
|
24
|
+
*
|
|
25
|
+
* has(cmp)(3)(setA) // true
|
|
26
|
+
* has(cmp)(2)(setA) // false
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
1
29
|
import type { Sign } from '../function/compare/module.f.ts';
|
|
2
30
|
export type SortedSet<T> = readonly T[];
|
|
3
31
|
type Cmp<T> = (a: T) => (b: T) => Sign;
|
|
@@ -7,6 +7,25 @@ import { flip } from "../function/module.f.js";
|
|
|
7
7
|
const stringify = a => json.stringify(sort)(a);
|
|
8
8
|
const reverseCmp = flip(unsafeCmp);
|
|
9
9
|
export default {
|
|
10
|
+
example: () => {
|
|
11
|
+
const cmp = (a) => (b) => a < b ? -1 : a > b ? 1 : 0;
|
|
12
|
+
const setA = [1, 3, 5];
|
|
13
|
+
const setB = [3, 4, 5];
|
|
14
|
+
const unionSet = union(cmp)(setA)(setB); // [1, 3, 4, 5]
|
|
15
|
+
if (stringify(unionSet) !== '[1,3,4,5]') {
|
|
16
|
+
throw 0;
|
|
17
|
+
}
|
|
18
|
+
const intersectionSet = intersect(cmp)(setA)(setB); // [3, 5]
|
|
19
|
+
if (stringify(intersectionSet) !== '[3,5]') {
|
|
20
|
+
throw 1;
|
|
21
|
+
}
|
|
22
|
+
if (!has(cmp)(3)(setA)) {
|
|
23
|
+
throw 2;
|
|
24
|
+
}
|
|
25
|
+
if (has(cmp)(2)(setA)) {
|
|
26
|
+
throw 3;
|
|
27
|
+
}
|
|
28
|
+
},
|
|
10
29
|
union: [
|
|
11
30
|
() => {
|
|
12
31
|
const result = stringify(toArray(union(unsafeCmp)([2, 3, 4])([1, 3, 5])));
|
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for working with strings and lists of strings.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
*
|
|
8
|
+
* ```js
|
|
9
|
+
* import { join, concat, repeat, cmp } from './module.f.ts'
|
|
10
|
+
*
|
|
11
|
+
* const words = ['hello', 'world']
|
|
12
|
+
* join(' ')(words) // 'hello world'
|
|
13
|
+
* concat(words) // 'helloworld'
|
|
14
|
+
* repeat('abc')(3) // 'abcabcabc'
|
|
15
|
+
* cmp('apple')('banana') // -1
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
1
18
|
import { type List } from '../list/module.f.ts';
|
|
2
19
|
import { type Sign } from '../function/compare/module.f.ts';
|
|
3
20
|
export declare const join: (_: string) => (input: List<string>) => string;
|