functionalscript 0.0.487 → 0.0.489

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.
Files changed (43) hide show
  1. package/README.md +4 -2
  2. package/com/cpp/module.f.cjs +1 -2
  3. package/com/cpp/test.f.cjs +1 -1
  4. package/com/cpp/testlib.f.cjs +1 -1
  5. package/com/test/build.f.cjs +1 -1
  6. package/commonjs/build/module.f.cjs +1 -1
  7. package/commonjs/build/test.f.cjs +2 -1
  8. package/commonjs/module/module.f.cjs +1 -1
  9. package/commonjs/path/module.f.cjs +5 -5
  10. package/dev/test.mjs +1 -1
  11. package/doc/predefined.md +2 -2
  12. package/fsc/test.f.cjs +1 -1
  13. package/json/module.f.cjs +4 -4
  14. package/package.json +1 -1
  15. package/text/README.md +2 -2
  16. package/text/utf8/module.f.cjs +15 -15
  17. package/types/array/module.f.cjs +9 -9
  18. package/types/array/test.f.cjs +1 -2
  19. package/types/btree/find/module.f.cjs +3 -3
  20. package/types/btree/module.f.cjs +2 -2
  21. package/types/btree/remove/module.f.cjs +11 -11
  22. package/types/btree/remove/test.f.cjs +52 -52
  23. package/types/btree/set/module.f.cjs +6 -6
  24. package/types/btree/test.f.cjs +2 -2
  25. package/types/btree/types/module.f.cjs +1 -1
  26. package/types/byte_set/module.f.cjs +8 -9
  27. package/types/list/module.f.cjs +61 -66
  28. package/types/list/test.f.cjs +9 -9
  29. package/types/map/module.f.cjs +7 -6
  30. package/types/map/test.f.cjs +9 -9
  31. package/types/nullable/module.f.cjs +17 -0
  32. package/types/{option → nullable}/test.f.cjs +2 -2
  33. package/types/number/module.f.cjs +2 -2
  34. package/types/number/test.f.cjs +1 -1
  35. package/types/range_map/module.f.cjs +6 -6
  36. package/types/range_map/test.f.cjs +2 -2
  37. package/types/sorted_list/module.f.cjs +13 -15
  38. package/types/sorted_list/test.f.cjs +2 -2
  39. package/types/sorted_set/module.f.cjs +4 -4
  40. package/types/sorted_set/test.f.cjs +0 -1
  41. package/types/string_set/module.f.cjs +2 -2
  42. package/types/string_set/test.f.cjs +3 -3
  43. package/types/option/module.f.cjs +0 -17
@@ -1,4 +1,5 @@
1
- const { compose, identity } = require('../function/module.f.cjs')
1
+ const function_ = require('../function/module.f.cjs')
2
+ const { identity, fn, compose } = function_
2
3
  const operator = require('../function/operator/module.f.cjs')
3
4
  const {
4
5
  counter,
@@ -23,7 +24,7 @@ const {
23
24
  * } NotLazy
24
25
  */
25
26
 
26
- /** @typedef {undefined} Empty */
27
+ /** @typedef {null} Empty */
27
28
 
28
29
  /**
29
30
  * @template T
@@ -46,8 +47,8 @@ const {
46
47
  /**
47
48
  * @template T
48
49
  * @typedef {{
49
- * readonly a: List<T>
50
- * readonly b: List<T>
50
+ * readonly head: List<T>
51
+ * readonly tail: List<T>
51
52
  * }} Concat
52
53
  */
53
54
 
@@ -55,41 +56,40 @@ const {
55
56
  const fromArray = array => {
56
57
  /** @typedef {typeof array extends readonly (infer T)[] ? T : never} T */
57
58
  /** @type {(i: number) => Result<T>} */
58
- const at = i => i < array.length ? { first: array[i], tail: () => at(i + 1) } : undefined
59
+ const at = i => i < array.length ? { first: array[i], tail: () => at(i + 1) } : null
59
60
  return at(0)
60
61
  }
61
62
 
62
- /** @type {<T>(a: List<T>) => (b: List<T>) => List<T>} */
63
- const concat = a => b => b === undefined ? a : ({ isConcat: true, a, b })
63
+ /** @type {<T>(head: List<T>) => (tail: List<T>) => List<T>} */
64
+ const concat = head => tail => tail === null ? head : ({ head, tail })
64
65
 
65
66
  /** @type {<T>(list: List<T>) => NotLazy<T> } */
66
67
  const trampoline = list => {
67
- let i = list
68
- while (typeof i === 'function') { i = i() }
69
- return i
68
+ while (typeof list === 'function') { list = list() }
69
+ return list
70
70
  }
71
71
 
72
72
  /** @type {<T>(list: List<T>) => Result<T>} */
73
- const next = list => {
74
- /** @type {readonly[typeof list, typeof list]} */
75
- let [a, b] = [list, undefined]
73
+ const next = head => {
74
+ /** @type {typeof head} */
75
+ let tail = null
76
76
  while (true) {
77
- a = trampoline(a)
77
+ head = trampoline(head)
78
78
 
79
- if (a instanceof Array) {
80
- a = fromArray(a)
81
- } else if (a !== undefined && 'a' in a) {
82
- [a, b] = [a.a, concat(a.b)(b)]
79
+ if (head instanceof Array) {
80
+ head = fromArray(head)
81
+ } else if (head !== null && 'head' in head) {
82
+ [head, tail] = [head.head, concat(head.tail)(tail)]
83
83
  continue
84
84
  }
85
85
 
86
- if (a !== undefined) {
87
- return { first: a.first, tail: concat(a.tail)(b) }
86
+ if (head !== null) {
87
+ return { first: head.first, tail: concat(head.tail)(tail) }
88
88
  }
89
89
 
90
- if (b === undefined) { return undefined }
90
+ if (tail === null) { return null }
91
91
 
92
- [a, b] = [b, undefined]
92
+ [head, tail] = [tail, null]
93
93
  }
94
94
  }
95
95
 
@@ -99,7 +99,7 @@ const iterable = list => ({
99
99
  let i = list
100
100
  while (true) {
101
101
  const r = next(i)
102
- if (r === undefined) { return }
102
+ if (r === null) { return }
103
103
  yield r.first
104
104
  i = r.tail
105
105
  }
@@ -117,18 +117,18 @@ const toArray = list => {
117
117
  /** @type {<I, O>(step: (n: NonEmpty<I>) => List<O>) => (input: List<I>) => Thunk<O>} */
118
118
  const apply = f => input => () => {
119
119
  const n = next(input)
120
- if (n === undefined) { return undefined }
120
+ if (n === null) { return null }
121
121
  return f(n)
122
122
  }
123
123
 
124
124
  /** @type {<T>(n: NonEmpty<List<T>>) => List<T>} */
125
- const flatStep = n => concat(n.first)(flat(n.tail))
125
+ const flatStep = ({ first, tail }) => concat(first)(flat(tail))
126
126
 
127
127
  /** @type {<T>(list: List<List<T>>) => Thunk<T>} */
128
128
  const flat = apply(flatStep)
129
129
 
130
130
  /** @type {<I, O>(f: (value: I) => O) => (n: NonEmpty<I>) => List<O>} */
131
- const mapStep = f => n => ({ first: f(n.first), tail: map(f)(n.tail) })
131
+ const mapStep = f => ({ first, tail }) => ({ first: f(first), tail: map(f)(tail) })
132
132
 
133
133
  /** @type {<I, O>(f: (value: I) => O) => (input: List<I>) => Thunk<O>} */
134
134
  const map = f => apply(mapStep(f))
@@ -137,31 +137,31 @@ const map = f => apply(mapStep(f))
137
137
  const flatMap = f => compose(map(f))(flat)
138
138
 
139
139
  /** @type {<T>(f: (value: T) => boolean) => (n: NonEmpty<T>) => List<T>} */
140
- const filterStep = f => n => {
141
- const tail = filter(f)(n.tail)
142
- return f(n.first) ? { first: n.first, tail } : tail
140
+ const filterStep = f => ({ first, tail }) => {
141
+ const newTail = filter(f)(tail)
142
+ return f(first) ? { first, tail: newTail } : newTail
143
143
  }
144
144
 
145
145
  /** @type {<T>(f: (value: T) => boolean) => (input: List<T>) => Thunk<T>} */
146
146
  const filter = f => apply(filterStep(f))
147
147
 
148
- /** @type {<I, O>(f: (value: I) => O|undefined) => (n: NonEmpty<I>) => List<O>} */
148
+ /** @type {<I, O>(f: (value: I) => O|null) => (n: NonEmpty<I>) => List<O>} */
149
149
  const filterMapStep = f => n => {
150
150
  const [first, tail] = [f(n.first), filterMap(f)(n.tail)]
151
- return first === undefined ? tail : { first, tail }
151
+ return first === null ? tail : { first, tail }
152
152
  }
153
153
 
154
- /** @type {<I, O>(f: (value: I) => O|undefined) => (input: List<I>) => Thunk<O>} */
154
+ /** @type {<I, O>(f: (value: I) => O|null) => (input: List<I>) => Thunk<O>} */
155
155
  const filterMap = f => apply(filterMapStep(f))
156
156
 
157
157
  /** @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) } : undefined
158
+ const takeWhileStep = f => ({ first, tail }) => f(first) ? { first, tail: takeWhile(f)(tail) } : null
159
159
 
160
160
  /** @type {<T>(f: (value: T) => boolean) => (input: List<T>) => Thunk<T>} */
161
161
  const takeWhile = f => apply(takeWhileStep(f))
162
162
 
163
163
  /** @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) } : undefined
164
+ const takeStep = n => ({ first, tail }) => 0 < n ? { first: first, tail: take(n - 1)(tail) } : null
165
165
 
166
166
  /** @type {(n: number) => <T>(input: List<T>) => Thunk<T>} */
167
167
  const take = n => apply(takeStep(n))
@@ -180,8 +180,8 @@ const drop = n => apply(dropStep(n))
180
180
 
181
181
  /** @type {<D>(def: D) => <T>(input: List<T>) => D|T} */
182
182
  const first = def => input => {
183
- const result = next(input)
184
- return result === undefined ? def : result.first
183
+ const ne = next(input)
184
+ return ne === null ? def : ne.first
185
185
  }
186
186
 
187
187
  /** @type {<D>(first: D) => <T>(tail: List<T>) => D|T} */
@@ -191,7 +191,7 @@ const last = first => tail => {
191
191
  let i = { first, tail }
192
192
  while (true) {
193
193
  const result = next(i.tail)
194
- if (result === undefined) {
194
+ if (result === null) {
195
195
  return i.first
196
196
  }
197
197
  i = result
@@ -199,43 +199,39 @@ const last = first => tail => {
199
199
  }
200
200
 
201
201
  /** @type {<D>(def: D) => <T>(f: (value: T) => boolean) => (input: List<T>) => D|T} */
202
- const find = def => f => input => first(def)(filter(f)(input))
203
-
204
- const findTrue = find(false)
202
+ const find = def => f => compose(filter(f))(first(def))
205
203
 
206
204
  /** @type {(input: List<boolean>) => boolean} */
207
- const some = input => findTrue
208
- (/** @type {(_: boolean) => boolean} */(identity))
209
- (input)
210
-
211
- /** @type {<T>(f: List<T>) => Thunk<boolean>} */
212
- const mapTrue = map(() => true)
205
+ const some = find(false)(identity)
213
206
 
214
207
  /** @type {<T>(input: List<T>) => boolean} */
215
- const isEmpty = input => !some(mapTrue(input))
208
+ const isEmpty = fn(map(() => true))
209
+ .then(some)
210
+ .then(logicalNot)
211
+ .result
216
212
 
217
- const mapNot = map(logicalNot)
218
-
219
- /** @type {(input: List<boolean>) => boolean} */
220
- const every = input => !some(mapNot(input))
213
+ const every = fn(map(logicalNot))
214
+ .then(some)
215
+ .then(logicalNot)
216
+ .result
221
217
 
222
218
  /** @type {<T>(value: T) => (sequence: List<T>) => boolean} */
223
- const includes = value => input => some(map(strictEqual(value))(input))
219
+ const includes = value => compose(map(strictEqual(value)))(some)
224
220
 
225
221
  /** @type {(count: number) => Thunk<number>} */
226
222
  const countdown = count => () => {
227
- if (count <= 0) { return undefined }
223
+ if (count <= 0) { return null }
228
224
  const first = count - 1
229
225
  return { first, tail: countdown(first) }
230
226
  }
231
227
 
232
228
  /** @type {<T>(v: T) => (c: number) => Thunk<T>} */
233
- const repeat = v => n => map(() => v)(countdown(n))
229
+ const repeat = v => compose(countdown)(map(() => v))
234
230
 
235
231
  /** @type {<T>(list: List<T>) => List<T>} */
236
232
  const cycle = list => () => {
237
233
  const i = next(list)
238
- return i === undefined ? undefined : { first: i.first, tail: concat(i.tail)(cycle(list)) }
234
+ return i === null ? null : { first: i.first, tail: concat(i.tail)(cycle(list)) }
239
235
  }
240
236
 
241
237
  /** @type {<I, O>(op: operator.Scan<I, O>) => (ne: NonEmpty<I>) => List<O>} */
@@ -248,17 +244,16 @@ const scanStep = op => ne => {
248
244
  const scan = op => apply(scanStep(op))
249
245
 
250
246
  /** @type {<I, S, O>(op: operator.StateScan<I, S, O>) => (init: S) => (input: List<I>) => Thunk<O>} */
251
- const stateScan = op => init => scan(stateScanToScan(op)(init))
247
+ const stateScan = op => compose(stateScanToScan(op))(scan)
252
248
 
253
249
  /** @type {<I,O>(op: operator.Fold<I, O>) => (init: O) => (input: List<I>) => Thunk<O>} */
254
- const foldScan = op => init => scan(foldToScan(op)(init))
250
+ const foldScan = op => compose(foldToScan(op))(scan)
255
251
 
256
252
  /** @type {<I,O>(op: operator.Fold<I, O>) => (init: O) => (input: List<I>) => O} */
257
- const fold = op => init => input => last(init)(foldScan(op)(init)(input))
253
+ const fold = op => init => compose(foldScan(op)(init))(last(init))
258
254
 
259
255
  /** @type {<T>(op: operator.Reduce<T>) => <D>(def: D) => (input: List<T>) => D|T} */
260
- const reduce = op => def => input => last(def)(scan(reduceToScan(op))(input))
261
-
256
+ const reduce = op => def => compose(scan(reduceToScan(op)))(last(def))
262
257
 
263
258
  /** @type {<T>(input: List<T>) => number} */
264
259
  const length = fold(counter)(0)
@@ -283,14 +278,14 @@ const entries = input => {
283
278
  const reverseOperator = first => tail => ({ first, tail })
284
279
 
285
280
  /** @type {<T>(input: List<T>) => List<T>} */
286
- const reverse = fold(reverseOperator)(undefined)
281
+ const reverse = fold(reverseOperator)(null)
287
282
 
288
283
  /** @type {<A>(a: List<A>) => <B>(b: List<B>) => List<readonly[A, B]>} */
289
284
  const zip = a => b => () => {
290
285
  const aResult = next(a)
291
- if (aResult === undefined) { return undefined }
286
+ if (aResult === null) { return null }
292
287
  const bResult = next(b)
293
- if (bResult === undefined) { return undefined }
288
+ if (bResult === null) { return null }
294
289
  return { first: [aResult.first, bResult.first], tail: zip(aResult.tail)(bResult.tail) }
295
290
  }
296
291
 
@@ -300,8 +295,8 @@ const equal = e => {
300
295
  /** @type {(a: List<T>) => (b: List<T>) => List<boolean>} */
301
296
  const f = a => b => () => {
302
297
  const [aResult, bResult] = [next(a), next(b)]
303
- return aResult === undefined || bResult === undefined
304
- ? { first: aResult === bResult, tail: undefined }
298
+ return aResult === null || bResult === null
299
+ ? { first: aResult === bResult, tail: null }
305
300
  : { first: e(aResult.first)(bResult.first), tail: f(aResult.tail)(bResult.tail) }
306
301
  }
307
302
  return a => b => every(f(a)(b))
@@ -309,7 +304,7 @@ const equal = e => {
309
304
 
310
305
  module.exports = {
311
306
  /** @readonly */
312
- empty: undefined,
307
+ empty: null,
313
308
  /** @readonly */
314
309
  concat,
315
310
  /** @readonly */
@@ -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 === undefined) { throw 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(undefined)(x => x % 2 === 0)([1, 3, 5, 7])
59
- if (result !== undefined) { throw 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(undefined)(x => x % 2 === 0)([1, 2, 3, 4])
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)(undefined)([2, 3, 4, 5])
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)(undefined)([])
110
- if (result !== undefined) { throw 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(undefined)(result)
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(() => undefined)(result))
247
+ const len = _.length(_.filterMap(() => null)(result))
248
248
  if (len !== 0) { throw len }
249
249
  },
250
250
  dropWhile: () => {
@@ -31,15 +31,16 @@ 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|undefined} */
34
+ /** @type {(name: string) => <T>(map: Map<T>) => T|null} */
35
35
  const at = name => map => {
36
- if (map === undefined) { return undefined }
36
+ if (map === null) { return null }
37
37
  const result = value(find(keyCmp(name))(map).first)
38
- return result === undefined ? undefined : result[1]
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 === undefined ? entry : [old[0], reduce(old[1])(entry[1])])
42
+ const setReduceEntry = reduce => entry =>
43
+ set(keyCmp(entry[0]))(old => old === null ? entry : [old[0], reduce(old[1])(entry[1])])
43
44
 
44
45
  /** @type {<T>(reduce: operator.Reduce<T>) => (name: string) => (value: T) => (map: Map<T>) => Map<T>} */
45
46
  const setReduce = reduce => name => value => setReduceEntry(reduce)([name, value])
@@ -54,14 +55,14 @@ const setReplace = name => value => setReduceEntry(replace)([name, value])
54
55
  const entries = values
55
56
 
56
57
  /** @type {<T>(entries: list.List<Entry<T>>) => Map<T>} */
57
- const fromEntries = fold(setReduceEntry(replace))(undefined)
58
+ const fromEntries = fold(setReduceEntry(replace))(null)
58
59
 
59
60
  /** @type {(name: string) => <T>(map: Map<T>) => Map<T>} */
60
61
  const remove = name => btreeRemove(keyCmp(name))
61
62
 
62
63
  module.exports = {
63
64
  /** @readonly */
64
- empty: undefined,
65
+ empty: null,
65
66
  /** @readonly */
66
67
  at,
67
68
  /** @readonly */
@@ -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)(undefined)
7
+ let m = setReplace('a')(1)(null)
8
8
 
9
9
  if (at('a')(m) !== 1) { throw 'error' }
10
- if (at('b')(m) !== undefined) { throw 'error' }
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) !== undefined) { throw 'error' }
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) !== undefined) { throw 'error' }
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) !== undefined) { throw 'error' }
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) !== undefined) { throw 'error' }
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) !== undefined) { throw 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)(undefined)
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) !== undefined) { throw 'error' }
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(undefined)
8
- if (sqUndefined !== undefined) { throw sqUndefined }
7
+ const sqNull = optionSq(null)
8
+ if (sqNull !== null) { throw sqNull }
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)(undefined)
8
+ const min = reduce(minOp)(null)
9
9
 
10
- const max = reduce(maxOp)(undefined)
10
+ const max = reduce(maxOp)(null)
11
11
 
12
12
  /** @type {(a: number) => (b: number) => compare.Sign} */
13
13
  const cmp = unsafeCmp
@@ -8,7 +8,7 @@ module.exports = {
8
8
  min: {
9
9
  empty: () => {
10
10
  const result = min([])
11
- if (result !== undefined) { throw result }
11
+ if (result !== null) { throw result }
12
12
  },
13
13
  multi: () => {
14
14
  const result = min([1, 2, 12, -4, 8])
@@ -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("../option/module.f.cjs")
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.Option<Entry<T>>} RangeState
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 !== undefined && equal(state[0])(u) ? undefined : 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 === undefined) { return tail }
54
+ if (state === null) { return tail }
55
55
  const tailResult = next(tail)
56
- if (tailResult === undefined) { return [state] }
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)})(undefined)
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 = undefined
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 = undefined
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('../option/module.f.cjs')
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.Option<T>, compare.Sign, S]} ReduceOp
25
+ * @typedef {(state: S) => (a: T) => (b: T) => readonly[option.Nullable<T>, compare.Sign, S]} ReduceOp
27
26
  */
28
27
 
29
28
  /**
@@ -42,54 +41,53 @@ const range = require('../range/module.f.cjs')
42
41
  */
43
42
 
44
43
  /** @type {<T,S>(reduce: MergeReduce<T,S>) => (state: S) => (a: list.List<T>) => (b: list.List<T>) => list.List<T>} */
45
- const genericMerge = reduce => {
46
- const { reduceOp, tailReduce } = reduce
47
- /** @typedef {typeof reduce extends MergeReduce<infer T, infer S> ? [T, S] : never} TS */
44
+ const genericMerge = ({ reduceOp, tailReduce }) => {
45
+ /** @typedef {typeof reduceOp extends ReduceOp<infer T, infer S> ? [T, S] : never} TS */
48
46
  /** @typedef {TS[0]} T */
49
47
  /** @typedef {TS[1]} S */
50
48
  /** @type {(state: S) => (a: list.List<T>) => (b: list.List<T>) => list.List<T>} */
51
49
  const f = state => a => b => () => {
52
50
  const aResult = next(a)
53
- if (aResult === undefined) { return tailReduce(state)(b) }
51
+ if (aResult === null) { return tailReduce(state)(b) }
54
52
  const bResult = next(b)
55
- if (bResult === undefined) { return tailReduce(state)(aResult) }
53
+ if (bResult === null) { return tailReduce(state)(aResult) }
56
54
  const [first, sign, stateNext] = reduceOp(state)(aResult.first)(bResult.first)
57
55
  const aNext = sign === 1 ? a : aResult.tail
58
56
  const bNext = sign === -1 ? b : bResult.tail
59
57
  const tail = f(stateNext)(aNext)(bNext)
60
- return first === undefined ? tail : { first, tail }
58
+ return first === null ? tail : { first, tail }
61
59
  }
62
60
  return f
63
61
  }
64
62
 
65
63
  /**
66
64
  * @template T
67
- * @typedef {ReduceOp<T, undefined>} CmpReduceOp
65
+ * @typedef {ReduceOp<T, null>} CmpReduceOp
68
66
  */
69
67
 
70
68
  /** @type {<T>(cmp: Cmp<T>) => (a: SortedList<T>) => (b: SortedList<T>) => SortedList<T>} */
71
69
  const merge = cmp => {
72
70
  /** @typedef {typeof cmp extends Cmp<infer T> ? T : never} T*/
73
- /** @type {TailReduce<T, undefined>} */
71
+ /** @type {TailReduce<T, null>} */
74
72
  const tailReduce = mergeTail
75
- return genericMerge({ reduceOp: cmpReduce(cmp), tailReduce })(undefined)
73
+ return genericMerge({ reduceOp: cmpReduce(cmp), tailReduce })(null)
76
74
  }
77
75
 
78
76
  /** @type {<T>(cmp: Cmp<T>) => CmpReduceOp<T>} */
79
77
  const cmpReduce = cmp => () => a => b => {
80
78
  const sign = cmp(a)(b)
81
- return [sign === 1 ? b : a, sign, undefined]
79
+ return [sign === 1 ? b : a, sign, null]
82
80
  }
83
81
 
84
82
  /** @type {() => <T>(tail: list.List<T>) => list.List<T>} */
85
83
  const mergeTail = () => identity
86
84
 
87
- /** @type {<T>(cmp: Cmp<T>) => (value: T) => (array: SortedArray<T>) => T|undefined} */
85
+ /** @type {<T>(cmp: Cmp<T>) => (value: T) => (array: SortedArray<T>) => T|null} */
88
86
  const find = cmp => value => array => {
89
87
  let b = 0
90
88
  let e = array.length - 1
91
89
  while (true) {
92
- if (e - b < 0) return undefined
90
+ if (e - b < 0) return null
93
91
  const mid = b + (e - b >> 1)
94
92
  const sign = cmp(value)(array[mid])
95
93
  switch(sign) {