functionalscript 0.0.486 → 0.0.488
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/com/cpp/module.f.cjs +1 -2
- package/com/cpp/test.f.cjs +1 -1
- package/com/cpp/testlib.f.cjs +1 -1
- package/com/rust/module.f.cjs +13 -9
- package/com/test/build.f.cjs +1 -1
- package/commonjs/build/module.f.cjs +1 -1
- package/commonjs/build/test.f.cjs +2 -1
- package/commonjs/module/module.f.cjs +1 -1
- package/commonjs/path/module.f.cjs +5 -5
- package/dev/test.mjs +1 -1
- package/doc/predefined.md +2 -2
- package/fsc/test.f.cjs +1 -1
- package/json/module.f.cjs +4 -4
- package/package.json +1 -1
- package/text/README.md +2 -2
- package/text/utf8/module.f.cjs +15 -15
- package/types/array/module.f.cjs +9 -6
- package/types/btree/find/module.f.cjs +3 -3
- package/types/btree/module.f.cjs +2 -2
- package/types/btree/remove/module.f.cjs +11 -11
- package/types/btree/remove/test.f.cjs +52 -52
- package/types/btree/set/module.f.cjs +6 -6
- package/types/btree/test.f.cjs +2 -2
- package/types/btree/types/module.f.cjs +1 -1
- package/types/byte_set/module.f.cjs +1 -1
- package/types/list/module.f.cjs +37 -38
- package/types/list/test.f.cjs +9 -9
- package/types/map/module.f.cjs +6 -6
- package/types/map/test.f.cjs +9 -9
- package/types/nullable/module.f.cjs +17 -0
- package/types/{option → nullable}/test.f.cjs +2 -2
- package/types/number/module.f.cjs +2 -2
- package/types/number/test.f.cjs +1 -1
- package/types/range_map/module.f.cjs +6 -6
- package/types/range_map/test.f.cjs +2 -2
- package/types/sorted_list/module.f.cjs +11 -12
- package/types/sorted_list/test.f.cjs +2 -2
- package/types/sorted_set/module.f.cjs +3 -3
- package/types/sorted_set/test.f.cjs +0 -1
- package/types/string_set/module.f.cjs +2 -2
- package/types/string_set/test.f.cjs +3 -3
- package/types/option/module.f.cjs +0 -17
package/types/list/module.f.cjs
CHANGED
|
@@ -23,7 +23,7 @@ const {
|
|
|
23
23
|
* } NotLazy
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
/** @typedef {
|
|
26
|
+
/** @typedef {null} Empty */
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* @template T
|
|
@@ -46,8 +46,8 @@ const {
|
|
|
46
46
|
/**
|
|
47
47
|
* @template T
|
|
48
48
|
* @typedef {{
|
|
49
|
-
* readonly
|
|
50
|
-
* readonly
|
|
49
|
+
* readonly head: List<T>
|
|
50
|
+
* readonly tail: List<T>
|
|
51
51
|
* }} Concat
|
|
52
52
|
*/
|
|
53
53
|
|
|
@@ -55,41 +55,40 @@ const {
|
|
|
55
55
|
const fromArray = array => {
|
|
56
56
|
/** @typedef {typeof array extends readonly (infer T)[] ? T : never} T */
|
|
57
57
|
/** @type {(i: number) => Result<T>} */
|
|
58
|
-
const at = i => i < array.length ? { first: array[i], tail: () => at(i + 1) } :
|
|
58
|
+
const at = i => i < array.length ? { first: array[i], tail: () => at(i + 1) } : null
|
|
59
59
|
return at(0)
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
/** @type {<T>(
|
|
63
|
-
const concat =
|
|
62
|
+
/** @type {<T>(head: List<T>) => (tail: List<T>) => List<T>} */
|
|
63
|
+
const concat = head => tail => tail === null ? head : ({ head, tail })
|
|
64
64
|
|
|
65
65
|
/** @type {<T>(list: List<T>) => NotLazy<T> } */
|
|
66
66
|
const trampoline = list => {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
return i
|
|
67
|
+
while (typeof list === 'function') { list = list() }
|
|
68
|
+
return list
|
|
70
69
|
}
|
|
71
70
|
|
|
72
71
|
/** @type {<T>(list: List<T>) => Result<T>} */
|
|
73
|
-
const next =
|
|
74
|
-
/** @type {
|
|
75
|
-
let
|
|
72
|
+
const next = head => {
|
|
73
|
+
/** @type {typeof head} */
|
|
74
|
+
let tail = null
|
|
76
75
|
while (true) {
|
|
77
|
-
|
|
76
|
+
head = trampoline(head)
|
|
78
77
|
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
} else if (
|
|
82
|
-
[
|
|
78
|
+
if (head instanceof Array) {
|
|
79
|
+
head = fromArray(head)
|
|
80
|
+
} else if (head !== null && 'head' in head) {
|
|
81
|
+
[head, tail] = [head.head, concat(head.tail)(tail)]
|
|
83
82
|
continue
|
|
84
83
|
}
|
|
85
84
|
|
|
86
|
-
if (
|
|
87
|
-
return { first:
|
|
85
|
+
if (head !== null) {
|
|
86
|
+
return { first: head.first, tail: concat(head.tail)(tail) }
|
|
88
87
|
}
|
|
89
88
|
|
|
90
|
-
if (
|
|
89
|
+
if (tail === null) { return null }
|
|
91
90
|
|
|
92
|
-
[
|
|
91
|
+
[head, tail] = [tail, null]
|
|
93
92
|
}
|
|
94
93
|
}
|
|
95
94
|
|
|
@@ -99,7 +98,7 @@ const iterable = list => ({
|
|
|
99
98
|
let i = list
|
|
100
99
|
while (true) {
|
|
101
100
|
const r = next(i)
|
|
102
|
-
if (r ===
|
|
101
|
+
if (r === null) { return }
|
|
103
102
|
yield r.first
|
|
104
103
|
i = r.tail
|
|
105
104
|
}
|
|
@@ -117,7 +116,7 @@ const toArray = list => {
|
|
|
117
116
|
/** @type {<I, O>(step: (n: NonEmpty<I>) => List<O>) => (input: List<I>) => Thunk<O>} */
|
|
118
117
|
const apply = f => input => () => {
|
|
119
118
|
const n = next(input)
|
|
120
|
-
if (n ===
|
|
119
|
+
if (n === null) { return null }
|
|
121
120
|
return f(n)
|
|
122
121
|
}
|
|
123
122
|
|
|
@@ -145,23 +144,23 @@ const filterStep = f => n => {
|
|
|
145
144
|
/** @type {<T>(f: (value: T) => boolean) => (input: List<T>) => Thunk<T>} */
|
|
146
145
|
const filter = f => apply(filterStep(f))
|
|
147
146
|
|
|
148
|
-
/** @type {<I, O>(f: (value: I) => O|
|
|
147
|
+
/** @type {<I, O>(f: (value: I) => O|null) => (n: NonEmpty<I>) => List<O>} */
|
|
149
148
|
const filterMapStep = f => n => {
|
|
150
149
|
const [first, tail] = [f(n.first), filterMap(f)(n.tail)]
|
|
151
|
-
return first ===
|
|
150
|
+
return first === null ? tail : { first, tail }
|
|
152
151
|
}
|
|
153
152
|
|
|
154
|
-
/** @type {<I, O>(f: (value: I) => O|
|
|
153
|
+
/** @type {<I, O>(f: (value: I) => O|null) => (input: List<I>) => Thunk<O>} */
|
|
155
154
|
const filterMap = f => apply(filterMapStep(f))
|
|
156
155
|
|
|
157
156
|
/** @type {<T>(f: (value: T) => boolean) => (n: NonEmpty<T>) => List<T>} */
|
|
158
|
-
const takeWhileStep = f => n => f(n.first) ? { first: n.first, tail: takeWhile(f)(n.tail) } :
|
|
157
|
+
const takeWhileStep = f => n => f(n.first) ? { first: n.first, tail: takeWhile(f)(n.tail) } : null
|
|
159
158
|
|
|
160
159
|
/** @type {<T>(f: (value: T) => boolean) => (input: List<T>) => Thunk<T>} */
|
|
161
160
|
const takeWhile = f => apply(takeWhileStep(f))
|
|
162
161
|
|
|
163
162
|
/** @type {(n: number) => <T>(result: NonEmpty<T>) => List<T>} */
|
|
164
|
-
const takeStep = n => ne => 0 < n ? { first: ne.first, tail: take(n - 1)(ne.tail) } :
|
|
163
|
+
const takeStep = n => ne => 0 < n ? { first: ne.first, tail: take(n - 1)(ne.tail) } : null
|
|
165
164
|
|
|
166
165
|
/** @type {(n: number) => <T>(input: List<T>) => Thunk<T>} */
|
|
167
166
|
const take = n => apply(takeStep(n))
|
|
@@ -181,7 +180,7 @@ const drop = n => apply(dropStep(n))
|
|
|
181
180
|
/** @type {<D>(def: D) => <T>(input: List<T>) => D|T} */
|
|
182
181
|
const first = def => input => {
|
|
183
182
|
const result = next(input)
|
|
184
|
-
return result ===
|
|
183
|
+
return result === null ? def : result.first
|
|
185
184
|
}
|
|
186
185
|
|
|
187
186
|
/** @type {<D>(first: D) => <T>(tail: List<T>) => D|T} */
|
|
@@ -191,7 +190,7 @@ const last = first => tail => {
|
|
|
191
190
|
let i = { first, tail }
|
|
192
191
|
while (true) {
|
|
193
192
|
const result = next(i.tail)
|
|
194
|
-
if (result ===
|
|
193
|
+
if (result === null) {
|
|
195
194
|
return i.first
|
|
196
195
|
}
|
|
197
196
|
i = result
|
|
@@ -224,7 +223,7 @@ const includes = value => input => some(map(strictEqual(value))(input))
|
|
|
224
223
|
|
|
225
224
|
/** @type {(count: number) => Thunk<number>} */
|
|
226
225
|
const countdown = count => () => {
|
|
227
|
-
if (count <= 0) { return
|
|
226
|
+
if (count <= 0) { return null }
|
|
228
227
|
const first = count - 1
|
|
229
228
|
return { first, tail: countdown(first) }
|
|
230
229
|
}
|
|
@@ -235,7 +234,7 @@ const repeat = v => n => map(() => v)(countdown(n))
|
|
|
235
234
|
/** @type {<T>(list: List<T>) => List<T>} */
|
|
236
235
|
const cycle = list => () => {
|
|
237
236
|
const i = next(list)
|
|
238
|
-
return i ===
|
|
237
|
+
return i === null ? null : { first: i.first, tail: concat(i.tail)(cycle(list)) }
|
|
239
238
|
}
|
|
240
239
|
|
|
241
240
|
/** @type {<I, O>(op: operator.Scan<I, O>) => (ne: NonEmpty<I>) => List<O>} */
|
|
@@ -283,14 +282,14 @@ const entries = input => {
|
|
|
283
282
|
const reverseOperator = first => tail => ({ first, tail })
|
|
284
283
|
|
|
285
284
|
/** @type {<T>(input: List<T>) => List<T>} */
|
|
286
|
-
const reverse = fold(reverseOperator)(
|
|
285
|
+
const reverse = fold(reverseOperator)(null)
|
|
287
286
|
|
|
288
287
|
/** @type {<A>(a: List<A>) => <B>(b: List<B>) => List<readonly[A, B]>} */
|
|
289
288
|
const zip = a => b => () => {
|
|
290
289
|
const aResult = next(a)
|
|
291
|
-
if (aResult ===
|
|
290
|
+
if (aResult === null) { return null }
|
|
292
291
|
const bResult = next(b)
|
|
293
|
-
if (bResult ===
|
|
292
|
+
if (bResult === null) { return null }
|
|
294
293
|
return { first: [aResult.first, bResult.first], tail: zip(aResult.tail)(bResult.tail) }
|
|
295
294
|
}
|
|
296
295
|
|
|
@@ -300,8 +299,8 @@ const equal = e => {
|
|
|
300
299
|
/** @type {(a: List<T>) => (b: List<T>) => List<boolean>} */
|
|
301
300
|
const f = a => b => () => {
|
|
302
301
|
const [aResult, bResult] = [next(a), next(b)]
|
|
303
|
-
return aResult ===
|
|
304
|
-
? { first: aResult === bResult, tail:
|
|
302
|
+
return aResult === null || bResult === null
|
|
303
|
+
? { first: aResult === bResult, tail: null }
|
|
305
304
|
: { first: e(aResult.first)(bResult.first), tail: f(aResult.tail)(bResult.tail) }
|
|
306
305
|
}
|
|
307
306
|
return a => b => every(f(a)(b))
|
|
@@ -309,7 +308,7 @@ const equal = e => {
|
|
|
309
308
|
|
|
310
309
|
module.exports = {
|
|
311
310
|
/** @readonly */
|
|
312
|
-
empty:
|
|
311
|
+
empty: null,
|
|
313
312
|
/** @readonly */
|
|
314
313
|
concat,
|
|
315
314
|
/** @readonly */
|
package/types/list/test.f.cjs
CHANGED
|
@@ -29,7 +29,7 @@ const flat = () => {
|
|
|
29
29
|
const concat = () => {
|
|
30
30
|
const result = _.concat([1])([2])
|
|
31
31
|
const x = _.next(result)
|
|
32
|
-
if (x ===
|
|
32
|
+
if (x === null) { throw x }
|
|
33
33
|
if (x.first !== 1) { throw x }
|
|
34
34
|
}
|
|
35
35
|
|
|
@@ -55,11 +55,11 @@ const take = [
|
|
|
55
55
|
|
|
56
56
|
const find = [
|
|
57
57
|
() => {
|
|
58
|
-
const result = _.find(
|
|
59
|
-
if (result !==
|
|
58
|
+
const result = _.find(null)(x => x % 2 === 0)([1, 3, 5, 7])
|
|
59
|
+
if (result !== null) { throw result }
|
|
60
60
|
},
|
|
61
61
|
() => {
|
|
62
|
-
const result = _.find(
|
|
62
|
+
const result = _.find(null)(x => x % 2 === 0)([1, 2, 3, 4])
|
|
63
63
|
if (result !== 2) { throw result }
|
|
64
64
|
}
|
|
65
65
|
]
|
|
@@ -102,12 +102,12 @@ const additionTests = [
|
|
|
102
102
|
if (result !== '[2,5,9,14]') { throw result }
|
|
103
103
|
},
|
|
104
104
|
() => {
|
|
105
|
-
const result = _.reduce(addition)(
|
|
105
|
+
const result = _.reduce(addition)(null)([2, 3, 4, 5])
|
|
106
106
|
if (result !== 14) { throw result }
|
|
107
107
|
},
|
|
108
108
|
() => {
|
|
109
|
-
const result = _.reduce(addition)(
|
|
110
|
-
if (result !==
|
|
109
|
+
const result = _.reduce(addition)(null)([])
|
|
110
|
+
if (result !== null) { throw result }
|
|
111
111
|
}
|
|
112
112
|
]
|
|
113
113
|
|
|
@@ -191,7 +191,7 @@ const stress = () => ({
|
|
|
191
191
|
const n = 50_000_000
|
|
192
192
|
const result = _.toArray(_.countdown(n))
|
|
193
193
|
if (result.length !== n) { throw result.length }
|
|
194
|
-
const first = _.first(
|
|
194
|
+
const first = _.first(null)(result)
|
|
195
195
|
if (first !== n - 1) { throw first }
|
|
196
196
|
},
|
|
197
197
|
concatBack: () => {
|
|
@@ -244,7 +244,7 @@ const stress = () => ({
|
|
|
244
244
|
const n = 50_000_000
|
|
245
245
|
const result = _.toArray(_.countdown(n))
|
|
246
246
|
if (result.length !== n) { throw result.length }
|
|
247
|
-
const len = _.length(_.filterMap(() =>
|
|
247
|
+
const len = _.length(_.filterMap(() => null)(result))
|
|
248
248
|
if (len !== 0) { throw len }
|
|
249
249
|
},
|
|
250
250
|
dropWhile: () => {
|
package/types/map/module.f.cjs
CHANGED
|
@@ -31,15 +31,15 @@ const operator = require('../function/operator/module.f.cjs')
|
|
|
31
31
|
/** @type {(a: string) => <T>(b: Entry<T>) => Sign} */
|
|
32
32
|
const keyCmp = a => ([b]) => cmp(a)(b)
|
|
33
33
|
|
|
34
|
-
/** @type {(name: string) => <T>(map: Map<T>) => T|
|
|
34
|
+
/** @type {(name: string) => <T>(map: Map<T>) => T|null} */
|
|
35
35
|
const at = name => map => {
|
|
36
|
-
if (map ===
|
|
36
|
+
if (map === null) { return null }
|
|
37
37
|
const result = value(find(keyCmp(name))(map).first)
|
|
38
|
-
return result ===
|
|
38
|
+
return result === null ? null : result[1]
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
/** @type {<T>(reduce: operator.Reduce<T>) => (entry: Entry<T>) => (map: Map<T>) => Map<T>} */
|
|
42
|
-
const setReduceEntry = reduce => entry => set(keyCmp(entry[0]))(old => old ===
|
|
42
|
+
const setReduceEntry = reduce => entry => set(keyCmp(entry[0]))(old => old === null ? entry : [old[0], reduce(old[1])(entry[1])])
|
|
43
43
|
|
|
44
44
|
/** @type {<T>(reduce: operator.Reduce<T>) => (name: string) => (value: T) => (map: Map<T>) => Map<T>} */
|
|
45
45
|
const setReduce = reduce => name => value => setReduceEntry(reduce)([name, value])
|
|
@@ -54,14 +54,14 @@ const setReplace = name => value => setReduceEntry(replace)([name, value])
|
|
|
54
54
|
const entries = values
|
|
55
55
|
|
|
56
56
|
/** @type {<T>(entries: list.List<Entry<T>>) => Map<T>} */
|
|
57
|
-
const fromEntries = fold(setReduceEntry(replace))(
|
|
57
|
+
const fromEntries = fold(setReduceEntry(replace))(null)
|
|
58
58
|
|
|
59
59
|
/** @type {(name: string) => <T>(map: Map<T>) => Map<T>} */
|
|
60
60
|
const remove = name => btreeRemove(keyCmp(name))
|
|
61
61
|
|
|
62
62
|
module.exports = {
|
|
63
63
|
/** @readonly */
|
|
64
|
-
empty:
|
|
64
|
+
empty: null,
|
|
65
65
|
/** @readonly */
|
|
66
66
|
at,
|
|
67
67
|
/** @readonly */
|
package/types/map/test.f.cjs
CHANGED
|
@@ -4,23 +4,23 @@ const seq = require('../list/module.f.cjs')
|
|
|
4
4
|
module.exports = {
|
|
5
5
|
main: [
|
|
6
6
|
() => {
|
|
7
|
-
let m = setReplace('a')(1)(
|
|
7
|
+
let m = setReplace('a')(1)(null)
|
|
8
8
|
|
|
9
9
|
if (at('a')(m) !== 1) { throw 'error' }
|
|
10
|
-
if (at('b')(m) !==
|
|
10
|
+
if (at('b')(m) !== null) { throw 'error' }
|
|
11
11
|
|
|
12
12
|
m = setReplace('b')(2)(m)
|
|
13
13
|
|
|
14
14
|
if (at('a')(m) !== 1) { throw 'error' }
|
|
15
15
|
if (at('b')(m) !== 2) { throw 'error' }
|
|
16
|
-
if (at('c')(m) !==
|
|
16
|
+
if (at('c')(m) !== null) { throw 'error' }
|
|
17
17
|
|
|
18
18
|
m = setReplace('z')(3)(m)
|
|
19
19
|
|
|
20
20
|
if (at('a')(m) !== 1) { throw 'error' }
|
|
21
21
|
if (at('b')(m) !== 2) { throw 'error' }
|
|
22
22
|
if (at('z')(m) !== 3) { throw 'error' }
|
|
23
|
-
if (at('')(m) !==
|
|
23
|
+
if (at('')(m) !== null) { throw 'error' }
|
|
24
24
|
|
|
25
25
|
m = setReplace('')(4)(m)
|
|
26
26
|
|
|
@@ -28,7 +28,7 @@ module.exports = {
|
|
|
28
28
|
if (at('b')(m) !== 2) { throw 'error' }
|
|
29
29
|
if (at('z')(m) !== 3) { throw 'error' }
|
|
30
30
|
if (at('')(m) !== 4) { throw 'error' }
|
|
31
|
-
if (at('Hello world!')(m) !==
|
|
31
|
+
if (at('Hello world!')(m) !== null) { throw 'error' }
|
|
32
32
|
|
|
33
33
|
m = setReplace('Hello world!')(42)(m)
|
|
34
34
|
|
|
@@ -37,21 +37,21 @@ module.exports = {
|
|
|
37
37
|
if (at('z')(m) !== 3) { throw 'error' }
|
|
38
38
|
if (at('')(m) !== 4) { throw 'error' }
|
|
39
39
|
if (at('Hello world!')(m) !== 42) { throw 'error' }
|
|
40
|
-
if (at('x')(m) !==
|
|
40
|
+
if (at('x')(m) !== null) { throw 'error' }
|
|
41
41
|
|
|
42
42
|
// console.log(Array.from(m.entries()))
|
|
43
43
|
m = remove('Hello world!')(m)
|
|
44
|
-
if (at('Hello world!')(m) !==
|
|
44
|
+
if (at('Hello world!')(m) !== null) { throw m }
|
|
45
45
|
|
|
46
46
|
m = setReduce(a => b => a + b)('a')(43)(m)
|
|
47
47
|
if (at('a')(m) !== 44) { throw 'error' }
|
|
48
48
|
},
|
|
49
49
|
() => {
|
|
50
|
-
let m = setReplace('x')(12)(
|
|
50
|
+
let m = setReplace('x')(12)(null)
|
|
51
51
|
m = setReplace('y')(44)(m)
|
|
52
52
|
if (at('x')(m) !== 12) { throw 'error' }
|
|
53
53
|
if (at('y')(m) !== 44) { throw 'error' }
|
|
54
|
-
if (at('a')(m) !==
|
|
54
|
+
if (at('a')(m) !== null) { throw 'error' }
|
|
55
55
|
const e = seq.toArray(entries(m))
|
|
56
56
|
if (e.length !== 2) { throw 'error' }
|
|
57
57
|
},
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @template T
|
|
3
|
+
* @typedef {T|null} Nullable
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** @type {<T, R>(f: (value: T) => R) => (value: Nullable<T>) => Nullable<R>} */
|
|
7
|
+
const map = f => value => value === null ? null : f(value)
|
|
8
|
+
|
|
9
|
+
/** @type {<T, R>(f: (_: T) => R) => (none: () => R) => (_: Nullable<T>) => Nullable<R>} */
|
|
10
|
+
const match = f => none => value => value === null ? none() : f(value)
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
/** @readonly */
|
|
14
|
+
map,
|
|
15
|
+
/** @readonly */
|
|
16
|
+
match,
|
|
17
|
+
}
|
|
@@ -4,6 +4,6 @@ module.exports = () => {
|
|
|
4
4
|
const optionSq = _.map(v => v * v)
|
|
5
5
|
const sq3 = optionSq(3)
|
|
6
6
|
if (sq3 !== 9) { throw sq3 }
|
|
7
|
-
const sqUndefined = optionSq(
|
|
8
|
-
if (sqUndefined !==
|
|
7
|
+
const sqUndefined = optionSq(null)
|
|
8
|
+
if (sqUndefined !== null) { throw sqUndefined }
|
|
9
9
|
}
|
|
@@ -5,9 +5,9 @@ const { unsafeCmp } = compare
|
|
|
5
5
|
|
|
6
6
|
const sum = reduce(addition)(0)
|
|
7
7
|
|
|
8
|
-
const min = reduce(minOp)(
|
|
8
|
+
const min = reduce(minOp)(null)
|
|
9
9
|
|
|
10
|
-
const max = reduce(maxOp)(
|
|
10
|
+
const max = reduce(maxOp)(null)
|
|
11
11
|
|
|
12
12
|
/** @type {(a: number) => (b: number) => compare.Sign} */
|
|
13
13
|
const cmp = unsafeCmp
|
package/types/number/test.f.cjs
CHANGED
|
@@ -2,7 +2,7 @@ const sortedList = require("../sorted_list/module.f.cjs")
|
|
|
2
2
|
const { genericMerge } = sortedList
|
|
3
3
|
const list = require("../list/module.f.cjs")
|
|
4
4
|
const { next } = list
|
|
5
|
-
const option = require("../
|
|
5
|
+
const option = require("../nullable/module.f.cjs")
|
|
6
6
|
const { cmp } = require('../number/module.f.cjs')
|
|
7
7
|
const operator = require("../function/operator/module.f.cjs")
|
|
8
8
|
const _range = require('../range/module.f.cjs')
|
|
@@ -32,7 +32,7 @@ const _range = require('../range/module.f.cjs')
|
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* @template T
|
|
35
|
-
* @typedef {option.
|
|
35
|
+
* @typedef {option.Nullable<Entry<T>>} RangeState
|
|
36
36
|
*/
|
|
37
37
|
|
|
38
38
|
/**
|
|
@@ -45,21 +45,21 @@ const reduceOp = union => equal => state => ([aItem, aMax]) => ([bItem, bMax])
|
|
|
45
45
|
const sign = cmp(aMax)(bMax)
|
|
46
46
|
const min = sign === 1 ? bMax : aMax
|
|
47
47
|
const u = union(aItem)(bItem)
|
|
48
|
-
const newState = state !==
|
|
48
|
+
const newState = state !== null && equal(state[0])(u) ? null : state
|
|
49
49
|
return [newState, sign, [u, min]]
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/** @type {<T>(equal: operator.Equal<T>) => sortedList.TailReduce<Entry<T>, RangeState<T>>} */
|
|
53
53
|
const tailReduce = equal => state => tail => {
|
|
54
|
-
if (state ===
|
|
54
|
+
if (state === null) { return tail }
|
|
55
55
|
const tailResult = next(tail)
|
|
56
|
-
if (tailResult ===
|
|
56
|
+
if (tailResult === null) { return [state] }
|
|
57
57
|
if (equal(state[0])(tailResult.first[0])) { return tailResult }
|
|
58
58
|
return { first: state, tail: tailResult }
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
/** @type {<T>(op: Operators<T>) => RangeMerge<T>} */
|
|
62
|
-
const merge = ({union, equal}) => genericMerge({reduceOp: reduceOp(union)(equal), tailReduce: tailReduce(equal)})(
|
|
62
|
+
const merge = ({union, equal}) => genericMerge({reduceOp: reduceOp(union)(equal), tailReduce: tailReduce(equal)})(null)
|
|
63
63
|
|
|
64
64
|
/** @type {<T>(def: T) => (value: number) => (rm: RangeMapArray<T>) => T} */
|
|
65
65
|
const get = def => value => rm => {
|
|
@@ -18,14 +18,14 @@ module.exports = {
|
|
|
18
18
|
/** @type {_.RangeMap<sortedSet.SortedSet<string>>} */
|
|
19
19
|
const a = [[['a'], 1], [['b'], 2]]
|
|
20
20
|
/** @type {_.RangeMap<sortedSet.SortedSet<string>>} */
|
|
21
|
-
const b =
|
|
21
|
+
const b = null
|
|
22
22
|
const merged = _.merge(op)(a)(b)
|
|
23
23
|
const result = stringify(list.toArray(merged))
|
|
24
24
|
if (result !== '[[["a"],1],[["b"],2]]') { throw result }
|
|
25
25
|
},
|
|
26
26
|
() => {
|
|
27
27
|
/** @type {_.RangeMap<sortedSet.SortedSet<string>>} */
|
|
28
|
-
const a =
|
|
28
|
+
const a = null
|
|
29
29
|
/** @type {_.RangeMap<sortedSet.SortedSet<string>>} */
|
|
30
30
|
const b = [[['a'], 1], [['b'], 2]]
|
|
31
31
|
const merged = _.merge(op)(a)(b)
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
const compare = require('../function/compare/module.f.cjs')
|
|
2
2
|
const list = require('../list/module.f.cjs')
|
|
3
|
-
const option = require('../
|
|
3
|
+
const option = require('../nullable/module.f.cjs')
|
|
4
4
|
const { next } = list
|
|
5
5
|
const { identity } = require('../function/module.f.cjs')
|
|
6
|
-
const range = require('../range/module.f.cjs')
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* @template T
|
|
@@ -23,7 +22,7 @@ const range = require('../range/module.f.cjs')
|
|
|
23
22
|
/**
|
|
24
23
|
* @template T
|
|
25
24
|
* @template S
|
|
26
|
-
* @typedef {(state: S) => (a: T) => (b: T) => readonly[option.
|
|
25
|
+
* @typedef {(state: S) => (a: T) => (b: T) => readonly[option.Nullable<T>, compare.Sign, S]} ReduceOp
|
|
27
26
|
*/
|
|
28
27
|
|
|
29
28
|
/**
|
|
@@ -50,46 +49,46 @@ const genericMerge = reduce => {
|
|
|
50
49
|
/** @type {(state: S) => (a: list.List<T>) => (b: list.List<T>) => list.List<T>} */
|
|
51
50
|
const f = state => a => b => () => {
|
|
52
51
|
const aResult = next(a)
|
|
53
|
-
if (aResult ===
|
|
52
|
+
if (aResult === null) { return tailReduce(state)(b) }
|
|
54
53
|
const bResult = next(b)
|
|
55
|
-
if (bResult ===
|
|
54
|
+
if (bResult === null) { return tailReduce(state)(aResult) }
|
|
56
55
|
const [first, sign, stateNext] = reduceOp(state)(aResult.first)(bResult.first)
|
|
57
56
|
const aNext = sign === 1 ? a : aResult.tail
|
|
58
57
|
const bNext = sign === -1 ? b : bResult.tail
|
|
59
58
|
const tail = f(stateNext)(aNext)(bNext)
|
|
60
|
-
return first ===
|
|
59
|
+
return first === null ? tail : { first, tail }
|
|
61
60
|
}
|
|
62
61
|
return f
|
|
63
62
|
}
|
|
64
63
|
|
|
65
64
|
/**
|
|
66
65
|
* @template T
|
|
67
|
-
* @typedef {ReduceOp<T,
|
|
66
|
+
* @typedef {ReduceOp<T, null>} CmpReduceOp
|
|
68
67
|
*/
|
|
69
68
|
|
|
70
69
|
/** @type {<T>(cmp: Cmp<T>) => (a: SortedList<T>) => (b: SortedList<T>) => SortedList<T>} */
|
|
71
70
|
const merge = cmp => {
|
|
72
71
|
/** @typedef {typeof cmp extends Cmp<infer T> ? T : never} T*/
|
|
73
|
-
/** @type {TailReduce<T,
|
|
72
|
+
/** @type {TailReduce<T, null>} */
|
|
74
73
|
const tailReduce = mergeTail
|
|
75
|
-
return genericMerge({ reduceOp: cmpReduce(cmp), tailReduce })(
|
|
74
|
+
return genericMerge({ reduceOp: cmpReduce(cmp), tailReduce })(null)
|
|
76
75
|
}
|
|
77
76
|
|
|
78
77
|
/** @type {<T>(cmp: Cmp<T>) => CmpReduceOp<T>} */
|
|
79
78
|
const cmpReduce = cmp => () => a => b => {
|
|
80
79
|
const sign = cmp(a)(b)
|
|
81
|
-
return [sign === 1 ? b : a, sign,
|
|
80
|
+
return [sign === 1 ? b : a, sign, null]
|
|
82
81
|
}
|
|
83
82
|
|
|
84
83
|
/** @type {() => <T>(tail: list.List<T>) => list.List<T>} */
|
|
85
84
|
const mergeTail = () => identity
|
|
86
85
|
|
|
87
|
-
/** @type {<T>(cmp: Cmp<T>) => (value: T) => (array: SortedArray<T>) => T|
|
|
86
|
+
/** @type {<T>(cmp: Cmp<T>) => (value: T) => (array: SortedArray<T>) => T|null} */
|
|
88
87
|
const find = cmp => value => array => {
|
|
89
88
|
let b = 0
|
|
90
89
|
let e = array.length - 1
|
|
91
90
|
while (true) {
|
|
92
|
-
if (e - b < 0) return
|
|
91
|
+
if (e - b < 0) return null
|
|
93
92
|
const mid = b + (e - b >> 1)
|
|
94
93
|
const sign = cmp(value)(array[mid])
|
|
95
94
|
switch(sign) {
|
|
@@ -37,11 +37,11 @@ module.exports = {
|
|
|
37
37
|
},
|
|
38
38
|
() => {
|
|
39
39
|
const result = _.find(unsafeCmp)(3)([0, 10, 20, 30, 40, 50, 60, 70, 80, 90])
|
|
40
|
-
if (result !==
|
|
40
|
+
if (result !== null) { throw result }
|
|
41
41
|
},
|
|
42
42
|
() => {
|
|
43
43
|
const result = _.find(unsafeCmp)(77)([0, 10, 20, 30, 40, 50, 60, 70, 80, 90])
|
|
44
|
-
if (result !==
|
|
44
|
+
if (result !== null) { throw result }
|
|
45
45
|
},
|
|
46
46
|
() => {
|
|
47
47
|
const result = _.find(unsafeCmp)(80)([0, 10, 20, 30, 40, 50, 60, 70, 80, 90])
|
|
@@ -22,15 +22,15 @@ const union = cmp => a => b => toArray(merge(cmp)(a)(b))
|
|
|
22
22
|
const intersect = cmp => a => b => toArray(intersectMerge(cmp)(a)(b))
|
|
23
23
|
|
|
24
24
|
/** @type {<T>(cmp: Cmp<T>) => (a: sortedList.SortedList<T>) => (b: sortedList.SortedList<T>) => sortedList.SortedList<T>} */
|
|
25
|
-
const intersectMerge = cmp => genericMerge({ reduceOp: intersectReduce(cmp), tailReduce: intersectTail })(
|
|
25
|
+
const intersectMerge = cmp => genericMerge({ reduceOp: intersectReduce(cmp), tailReduce: intersectTail })(null)
|
|
26
26
|
|
|
27
27
|
/** @type {<T,S>(cmp: Cmp<T>) => sortedList.ReduceOp<T,S>} */
|
|
28
28
|
const intersectReduce = cmp => state => a => b => {
|
|
29
29
|
const sign = cmp(a)(b)
|
|
30
|
-
return [sign === 0 ? a :
|
|
30
|
+
return [sign === 0 ? a : null, sign, state]
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
const intersectTail = () => () =>
|
|
33
|
+
const intersectTail = () => () => null
|
|
34
34
|
|
|
35
35
|
/** @type {<T>(cmp: Cmp<T>) => (value: T) => (set: SortedSet<T>) => boolean} */
|
|
36
36
|
const has = cmp => value => set => find(cmp)(value)(set) === value
|
|
@@ -18,13 +18,13 @@ const { compose } = require('../function/module.f.cjs')
|
|
|
18
18
|
/** @type {(value: string) => (set: StringSet) => boolean} */
|
|
19
19
|
const contains = value => {
|
|
20
20
|
const f = find(cmp(value))
|
|
21
|
-
return s => s !==
|
|
21
|
+
return s => s !== null && isFound(f(s).first)
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/** @type {(value: string) => (s: StringSet) => StringSet} */
|
|
25
25
|
const set = value => btreeSet(cmp(value))(() => value)
|
|
26
26
|
|
|
27
|
-
const fromValues = fold(set)(
|
|
27
|
+
const fromValues = fold(set)(null)
|
|
28
28
|
|
|
29
29
|
/** @type {(value: string) => (s: StringSet) => StringSet} */
|
|
30
30
|
const remove = compose(cmp)(btreeRemove)
|
|
@@ -2,12 +2,12 @@ const _ = require('./module.f.cjs')
|
|
|
2
2
|
|
|
3
3
|
module.exports = {
|
|
4
4
|
contains: () => {
|
|
5
|
-
const r = _.set('hello')(
|
|
5
|
+
const r = _.set('hello')(null)
|
|
6
6
|
if (!_.contains('hello')(r)) { throw r }
|
|
7
7
|
if (_.contains('hello1')(r)) { throw r }
|
|
8
8
|
},
|
|
9
9
|
remove: () => {
|
|
10
|
-
let r = _.set('hello')(
|
|
10
|
+
let r = _.set('hello')(null)
|
|
11
11
|
r = _.set('world')(r)
|
|
12
12
|
r = _.set('HELLO')(r)
|
|
13
13
|
r = _.set('WORLD!')(r)
|
|
@@ -29,6 +29,6 @@ module.exports = {
|
|
|
29
29
|
if (_.contains('HELLO')(r)) { throw r }
|
|
30
30
|
if (!_.contains('WORLD!')(r)) { throw r }
|
|
31
31
|
r = _.remove('WORLD!')(r)
|
|
32
|
-
if (r !==
|
|
32
|
+
if (r !== null) { throw r }
|
|
33
33
|
}
|
|
34
34
|
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @template T
|
|
3
|
-
* @typedef {T|undefined} Option
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/** @type {<T, R>(f: (value: T) => R) => (value: T|undefined) => R|undefined} */
|
|
7
|
-
const map = f => value => value === undefined ? undefined : f(value)
|
|
8
|
-
|
|
9
|
-
/** @type {<T, R>(f: (_: T) => R) => (none: () => R) => (_: T|undefined) => R|undefined} */
|
|
10
|
-
const match = f => none => value => value === undefined ? none() : f(value)
|
|
11
|
-
|
|
12
|
-
module.exports = {
|
|
13
|
-
/** @readonly */
|
|
14
|
-
map,
|
|
15
|
-
/** @readonly */
|
|
16
|
-
match,
|
|
17
|
-
}
|