functionalscript 0.0.185 → 0.0.186

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/btree/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  const { index3, index5 } = require('../cmp')
2
- const list = require('../sequence/list')
3
- const { pipe } = require('../function')
2
+ const seq = require('../sequence')
4
3
 
5
4
  /**
6
5
  * @template T
@@ -306,66 +305,38 @@ const replaceVisitor = {
306
305
  notFound: notFoundGet,
307
306
  }
308
307
 
309
- /** @type {<T>(_: Node<T>) => Iterable<T>} */
310
- const values = node => ({
311
- *[Symbol.iterator]() {
312
- switch (node.length) {
313
- case 1: case 2: {
314
- yield* node
315
- return
316
- }
317
- case 3: {
318
- yield* values(node[0])
319
- yield node[1]
320
- yield* values(node[2])
321
- return
322
- }
323
- default: {
324
- yield* values(node[0])
325
- yield node[1]
326
- yield* values(node[2])
327
- yield node[3]
328
- yield* values(node[4])
329
- return
330
- }
331
- }
332
- }
333
- })
308
+ /** @type {<T>(...array: readonly seq.Sequence<T>[]) => seq.Sequence<T>} */
309
+ const flatArray = (...array) => seq.flat(seq.fromArray(array))
334
310
 
335
- /** @type {<T>(...array: readonly list.List<T>[]) => list.List<T>} */
336
- const flatArray = (...array) => list.flat(list.fromArray(array))
337
-
338
- /** @type {<T>(node: Node<T>) => list.List<T>} */
311
+ /** @type {<T>(node: Node<T>) => seq.Sequence<T>} */
339
312
  const valuesList = node => () => {
340
313
  const f = () => {
341
314
  switch (node.length) {
342
- case 1: case 2: { return list.fromArray(node) }
315
+ case 1: case 2: { return seq.fromArray(node) }
343
316
  case 3: {
344
317
  return flatArray(
345
318
  valuesList(node[0]),
346
- list.one(node[1]),
319
+ seq.one(node[1]),
347
320
  valuesList(node[2])
348
321
  )
349
322
  }
350
323
  default: {
351
324
  return flatArray(
352
325
  valuesList(node[0]),
353
- list.one(node[1]),
326
+ seq.one(node[1]),
354
327
  valuesList(node[2]),
355
- list.one(node[3]),
328
+ seq.one(node[3]),
356
329
  valuesList(node[4])
357
330
  )
358
331
  }
359
332
  }
360
333
  }
361
- return list.next(f())
334
+ return seq.next(f())
362
335
  }
363
336
 
364
337
  module.exports = {
365
338
  /** @readonly */
366
339
  valuesList,
367
- /** @readonly */
368
- values,
369
340
  /**
370
341
  * @readonly
371
342
  * @type { <T>(cmp: Cmp<T>) => (node: Node<T>) => T|undefined }
package/btree/test.js CHANGED
@@ -1,7 +1,7 @@
1
1
  const btree = require('.')
2
2
  const { setVisitor, valuesList } = btree
3
3
  const { cmp } = require('../cmp')
4
- const list = require('../sequence/list')
4
+ const list = require('../sequence')
5
5
 
6
6
  /** @type {(node: btree.Node<string>) => (value: string) => btree.Node<string>} */
7
7
  const set = node => value => {
@@ -21,7 +21,7 @@ const test = () => {
21
21
  node = set(node)('f')
22
22
  //
23
23
  {
24
- /** @type {import('../sequence/list').Result<string>} */
24
+ /** @type {import('../sequence').Result<string>} */
25
25
  let result = list.next(valuesList(node))
26
26
  while (result !== undefined) {
27
27
  const t = result[0]
package/map/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  const option = require("../option")
2
2
  const { getVisitor, setVisitor, valuesList } = require("../btree")
3
3
  const { cmp } = require("../cmp")
4
- const list = require("../sequence/list")
4
+ const list = require("../sequence")
5
5
 
6
6
  /** @typedef {import("../cmp").Sign} Sign */
7
7
 
@@ -30,7 +30,7 @@ const list = require("../sequence/list")
30
30
  * @typedef {{
31
31
  * readonly get: (name: string) => T|undefined
32
32
  * readonly set: (name: string) => (value: T) => Map<T>
33
- * readonly entries: list.List<Entry<T>>
33
+ * readonly entries: list.Sequence<Entry<T>>
34
34
  * readonly root: undefined|TNode<Entry<T>>
35
35
  * }} Map
36
36
  */
package/map/test.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const { empty } = require('.')
2
- const list = require('../sequence/list')
2
+ const list = require('../sequence')
3
3
 
4
4
  {
5
5
  let m = empty.set('a')(1)
@@ -3,7 +3,7 @@ const { pipe } = require('../function')
3
3
  const option = require('../option')
4
4
  const { head, last, splitLast, splitFirst } = array
5
5
  const iter = require('../sequence/iterable')
6
- const seq = require('../sequence')
6
+ const seq = require('../sequence/operator')
7
7
 
8
8
  /**
9
9
  * @template T
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.185",
3
+ "version": "0.0.186",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,5 +1,5 @@
1
1
  const { pipe } = require('../../function')
2
- const seq = require('..')
2
+ const seq = require('../operator')
3
3
 
4
4
  /**
5
5
  * @template T
package/sequence/index.js CHANGED
@@ -1,92 +1,304 @@
1
- const op = require('../function/operator')
1
+ const array = require('./array')
2
+ const seqOp = require('./operator')
3
+ const { pipe } = require('../function')
4
+ const { logicalNot, strictEqual } = require('../function/operator')
2
5
 
3
6
  /**
4
- * @template T0
5
- * @template T1
6
- * @typedef {import('./array').Tuple2<T0, T1>} Tuple2
7
+ * @template T
8
+ * @typedef {() => Result<T>} SequenceFn
7
9
  */
8
10
 
9
11
  /**
10
12
  * @template T
11
- * @template R
12
- * @typedef {Tuple2<R, Scan<T, R>>} ScanResult
13
+ * @typedef {readonly [Sequence<T>, Sequence<T>]} Concat
13
14
  */
14
15
 
15
16
  /**
17
+ * Use `next` function to get `first` and `tail` of the list.
18
+ *
19
+ * Please note that the sequence also contains `Concat<T>. We need this as
20
+ * a workaround because modern JavaScript implementations don't support
21
+ * ES6 TCO (Tail Call Optimization). Without this wotkaround we may have
22
+ * a stack overflow if a list contains a lot of concateneted lists.
23
+ *
16
24
  * @template T
17
- * @template R
18
- * @typedef {(value: T) => ScanResult<T, R>} Scan
25
+ * @typedef { SequenceFn<T> | Concat<T>} Sequence
19
26
  */
20
27
 
21
28
  /**
22
29
  * @template T
23
- * @template R
24
- * @typedef {Tuple2<R, Scan<T, R>>} ExclusiveScan
30
+ * @typedef {FirstAndTail<T>|undefined} Result<T>
25
31
  */
26
32
 
27
- /** @type {<R, T>(operator: op.ReduceOperator<R, T>) => (prior: R) => Scan<T, R>} */
28
- const scan = operator => {
29
- /** @typedef {typeof operator extends op.ReduceOperator<infer R, infer T> ? [R, T] : never} RT */
30
- /** @typedef {RT[0]} R */
31
- /** @typedef {RT[1]} T */
32
- /** @type {(prior: R) => Scan<T, R>} */
33
- const f = prior => value => {
34
- const result = operator(prior)(value)
35
- return [result, f(result)]
36
- }
37
- return f
38
- }
39
-
40
- /** @type {<R, T>(operator: op.ReduceOperator<R, T>) => (first: R) => ExclusiveScan<T, R>} */
41
- const exclusiveScan = operator => first => [first, scan(operator)(first)]
42
-
43
- /**
33
+ /**
44
34
  * @template T
45
- * @typedef {Tuple2<number, T>} Entry
35
+ * @typedef {array.Tuple2<T, Sequence<T>>} FirstAndTail
46
36
  */
47
37
 
48
- /** @type {(index: number) => <T>(value: T) => ScanResult<T, Entry<T>>} */
49
- const createEntries = index => value => [[index, value], createEntries(index + 1)]
50
-
51
- const entries = createEntries(0)
38
+ const empty = () => undefined
52
39
 
53
- /** @type {(separator: string) => ExclusiveScan<string, string>} */
54
- const join = separator => ['', value => [value, scan(op.join(separator))(value)]]
40
+ /** @type {<F, T>(a: readonly[F, Sequence<T>]) => (b: Sequence<T>) => readonly[F, Sequence<T>]} */
41
+ const norm = ([a0, a1]) => b => [a0, [a1, b]]
55
42
 
56
- const sum = exclusiveScan(op.addition)(0)
43
+ /** @type {<T>(input: Sequence<T>) => Result<T>} */
44
+ const next = input => {
45
+ let i = input
46
+ while (true) {
47
+ if (typeof i === 'function') { return i() }
48
+ const [a, b] = i
49
+ if (typeof a === 'function') {
50
+ const result = a()
51
+ if (result !== undefined) {
52
+ return norm(result)(b)
53
+ }
54
+ i = b
55
+ } else {
56
+ i = norm(a)(b)
57
+ }
58
+ }
59
+ }
57
60
 
58
- /** @type {(a: number) => () => number} */
59
- const counter = a => () => a + 1
61
+ /** @type {<T>(input: Sequence<T>) => T|undefined} */
62
+ const first = input => {
63
+ const result = next(input)
64
+ if (result === undefined) { return undefined }
65
+ return result[0]
66
+ }
60
67
 
61
- const length = exclusiveScan(counter)(0)
68
+ /**
69
+ * @template T
70
+ * @template R
71
+ * @typedef {(list: Sequence<T>) => Sequence<R>} SequenceMap
72
+ */
62
73
 
63
74
  /**
64
75
  * @template T
65
76
  * @template R
66
- * @typedef {(value: T) => R} Func
77
+ * @typedef {(list: Sequence<T>) => R} SequenceReduce
67
78
  */
68
79
 
69
- /** @type {<T, R, X>(flatMap: (f: Func<T, readonly[R]>) => X) => (f: Func<T, R>) =>X} */
70
- const map = flatMap => f => flatMap(x => [f(x)])
80
+ /** @type {<T>(first: T) => Sequence<T>} */
81
+ const one = first => () => [first, empty]
82
+
83
+ /** @type {<T>(array: array.Array<T>) => Sequence<T>} */
84
+ const fromArray = a => {
85
+ /** @typedef {typeof a extends array.Array<infer T> ? T : never} T */
86
+ /** @type {(index: number) => Sequence<T>} */
87
+ const at = index => () => {
88
+ const result = array.at(index)(a)
89
+ if (result === undefined) { return undefined }
90
+ return [result[0], at(index + 1)]
91
+ }
92
+ return at(0)
93
+ }
94
+
95
+ /** @type {<T>(a: Sequence<T>) => SequenceMap<T, T>} */
96
+ const concat = a => b => [a, b]
97
+
98
+ /** @type {<T, R>(f: (value: T) => Sequence<R>) => SequenceMap<T, R>} */
99
+ const flatMap = f => input => () => {
100
+ let i = input
101
+ while (true) {
102
+ const result = next(i)
103
+ if (result === undefined) { return undefined }
104
+ const [first, tail] = result
105
+ const firstResult = next(f(first))
106
+ if (firstResult !== undefined) {
107
+ return norm(firstResult)(flatMap(f)(tail))
108
+ }
109
+ i = tail
110
+ }
111
+ }
112
+
113
+ /** @type {<T>(list: Sequence<Sequence<T>>) => Sequence<T>} */
114
+ const flat = flatMap(i => i)
115
+
116
+ /** @type {<T, R>(f: (value: T) => R) => SequenceMap<T, R>} */
117
+ const map = f => flatMap(i => one(f(i)))
118
+
119
+ /** @type {<T>(f: (value: T) => boolean) => SequenceMap<T, T>} */
120
+ const filter = f => flatMap(i => f(i) ? one(i) : empty)
121
+
122
+ /** @type {<T, R>(f: (value: T) => R|undefined) => (value: T) => Sequence<R>} */
123
+ const filterMapFunc = f => i => {
124
+ const result = f(i)
125
+ if (result === undefined) { return empty }
126
+ return one(result)
127
+ }
128
+
129
+ /** @type {<T, R>(f: (value: T) => R|undefined) => SequenceMap<T, R>} */
130
+ const filterMap = f => flatMap(filterMapFunc(f))
131
+
132
+ /** @type {<T, R>(s: seqOp.Scan<T, R>) => SequenceMap<T, R>} */
133
+ const scan = s => input => () => {
134
+ const result = next(input)
135
+ if (result === undefined) {
136
+ return result
137
+ }
138
+ const [first, tail] = result
139
+ const [newFirst, newS] = s(first)
140
+ return [newFirst, scan(newS)(tail)]
141
+ }
142
+
143
+ /** @type {<T, R>(s: seqOp.ExclusiveScan<T, R>) => SequenceMap<T, R>} */
144
+ const exclusiveScan = ([first, s]) => input => () => [first, scan(s)(input)]
145
+
146
+ /** @type {<T>(def: T) => (input: Sequence<T>) => T} */
147
+ const last = def => input => {
148
+ let r = def
149
+ let i = input
150
+ while (true) {
151
+ const result = next(i)
152
+ if (result === undefined) {
153
+ return r
154
+ }
155
+ r = result[0]
156
+ i = result[1]
157
+ }
158
+ }
159
+
160
+ /** @type {<T, R>(s: seqOp.ExclusiveScan<T, R>) => (input: Sequence<T>) => R} */
161
+ const reduce = ([first, s]) => input => last(first)(scan(s)(input))
162
+
163
+ const entries = scan(seqOp.entries)
164
+
165
+ const sum = reduce(seqOp.sum)
166
+
167
+ const length = reduce(seqOp.length)
168
+
169
+ const join = pipe(seqOp.join)(reduce)
170
+
171
+ /** @type {<T>(f: (value: T) => boolean) => SequenceMap<T, T>} */
172
+ const takeWhile = f => input => () => {
173
+ const result = next(input)
174
+ if (result === undefined || !f(result[0])) { return undefined }
175
+ return result
176
+ }
177
+
178
+ /** @type {(n: number) => <T>(input: Sequence<T>) => Sequence<T>} */
179
+ const drop = n => input => () => {
180
+ let iN = n
181
+ let iInput = input
182
+ while (true) {
183
+ const result = next(iInput)
184
+ if (iN <= 0 || result === undefined) { return result }
185
+ iN = iN - 1
186
+ iInput = result[1]
187
+ }
188
+ }
189
+
190
+ /** @type {(n: number) => <T>(input: Sequence<T>) => T|undefined} */
191
+ const at = n => input => first(drop(n)(input))
192
+
193
+ /** @type {<T>(f: (value: T) => boolean) => SequenceReduce<T, T|undefined>} */
194
+ const find = f => input => first(filter(f)(input))
195
+
196
+ /** @type {<T>(f: (value: T) => boolean) => SequenceReduce<T, boolean>} */
197
+ const some = f => input => find(x => x)(map(f)(input)) !== undefined
198
+
199
+ /** @type {<T>(value: T) => SequenceReduce<T, boolean>} */
200
+ const includes = value => some(strictEqual(value))
201
+
202
+ /** @type {<T>(f: (value: T) => boolean) => SequenceReduce<T, boolean>} */
203
+ const every = f => input => !some(pipe(f)(logicalNot))(input)
204
+
205
+ /** @type {<T>(list: Sequence<T>) => Iterable<T>} */
206
+ const iterable = list => ({
207
+ *[Symbol.iterator]() {
208
+ let i = list
209
+ while (true) {
210
+ const result = next(i)
211
+ if (result === undefined) { return }
212
+ yield result[0]
213
+ i = result[1]
214
+ }
215
+ }
216
+ })
217
+
218
+ /** @type {<T>(list: Sequence<T>) => AsyncIterable<T>} */
219
+ const asyncIterable = list => ({
220
+ async *[Symbol.asyncIterator]() {
221
+ let i = list
222
+ while (true) {
223
+ const result = next(i)
224
+ if (result === undefined) { return }
225
+ yield result[0]
226
+ i = result[1]
227
+ }
228
+ }
229
+ })
230
+
231
+ /** @type {<A>(a: Sequence<A>) => <B>(b: Sequence<B>) => Sequence<array.Tuple2<A, B>>} */
232
+ const zip = a => b => () => {
233
+ const resultA = next(a)
234
+ if (resultA === undefined) { return undefined }
235
+ const resultB = next(b)
236
+ if (resultB === undefined) { return undefined }
237
+ return [[resultA[0], resultB[0]], zip(resultA[1])(resultB[1])]
238
+ }
71
239
 
72
- /** @type {<T, X>(flatMap: (f: Func<T, readonly[T]|[]>) => X) => (f: Func<T, boolean>) =>X} */
73
- const filter = flatMap => f => flatMap(x => f(x) ? [x] : [])
240
+ /** @type {<T>(list: Sequence<T>) => readonly T[]} */
241
+ const toArray = input => Array.from(iterable(input))
74
242
 
75
243
  module.exports = {
76
244
  /** @readonly */
77
- exclusiveScan,
245
+ next,
246
+ /** @readonly */
247
+ one,
248
+ /** @readonly */
249
+ empty,
250
+ /** @readonly */
251
+ at,
252
+ /** @readonly */
253
+ concat,
254
+ /** @readonly */
255
+ first,
256
+ /** @readonly */
257
+ fromArray,
258
+ /** @readonly */
259
+ toArray,
260
+ /** @readonly */
261
+ iterable,
262
+ /** @readonly */
263
+ asyncIterable,
264
+ /** @readonly */
265
+ flatMap,
266
+ /** @readonly */
267
+ flat,
268
+ /** @readonly */
269
+ map,
270
+ /** @readonly */
271
+ filter,
272
+ /** @readonly */
273
+ filterMap,
78
274
  /** @readonly */
79
275
  scan,
80
276
  /** @readonly */
81
- join,
277
+ exclusiveScan,
278
+ /** @readonly */
279
+ last,
280
+ /** @readonly */
281
+ reduce,
282
+ /** @readonly */
283
+ entries,
82
284
  /** @readonly */
83
285
  sum,
84
286
  /** @readonly */
287
+ join,
288
+ /** @readonly */
85
289
  length,
86
290
  /** @readonly */
87
- entries,
291
+ drop,
88
292
  /** @readonly */
89
- map,
293
+ find,
90
294
  /** @readonly */
91
- filter,
92
- }
295
+ takeWhile,
296
+ /** @readonly */
297
+ some,
298
+ /** @readonly */
299
+ every,
300
+ /** @readonly */
301
+ includes,
302
+ /** @readonly */
303
+ zip,
304
+ }
@@ -1,5 +1,5 @@
1
1
  const { pipe } = require('../../function')
2
- const seq = require('..')
2
+ const seq = require('../operator')
3
3
 
4
4
  /** @type {<T>(a: Iterable<T>) => (b: Iterable<T>) => Iterable<T>} */
5
5
  const concat = a => b => ({
@@ -0,0 +1,92 @@
1
+ const op = require('../../function/operator')
2
+
3
+ /**
4
+ * @template T0
5
+ * @template T1
6
+ * @typedef {import('../array').Tuple2<T0, T1>} Tuple2
7
+ */
8
+
9
+ /**
10
+ * @template T
11
+ * @template R
12
+ * @typedef {Tuple2<R, Scan<T, R>>} ScanResult
13
+ */
14
+
15
+ /**
16
+ * @template T
17
+ * @template R
18
+ * @typedef {(value: T) => ScanResult<T, R>} Scan
19
+ */
20
+
21
+ /**
22
+ * @template T
23
+ * @template R
24
+ * @typedef {Tuple2<R, Scan<T, R>>} ExclusiveScan
25
+ */
26
+
27
+ /** @type {<R, T>(operator: op.ReduceOperator<R, T>) => (prior: R) => Scan<T, R>} */
28
+ const scan = operator => {
29
+ /** @typedef {typeof operator extends op.ReduceOperator<infer R, infer T> ? [R, T] : never} RT */
30
+ /** @typedef {RT[0]} R */
31
+ /** @typedef {RT[1]} T */
32
+ /** @type {(prior: R) => Scan<T, R>} */
33
+ const f = prior => value => {
34
+ const result = operator(prior)(value)
35
+ return [result, f(result)]
36
+ }
37
+ return f
38
+ }
39
+
40
+ /** @type {<R, T>(operator: op.ReduceOperator<R, T>) => (first: R) => ExclusiveScan<T, R>} */
41
+ const exclusiveScan = operator => first => [first, scan(operator)(first)]
42
+
43
+ /**
44
+ * @template T
45
+ * @typedef {Tuple2<number, T>} Entry
46
+ */
47
+
48
+ /** @type {(index: number) => <T>(value: T) => ScanResult<T, Entry<T>>} */
49
+ const createEntries = index => value => [[index, value], createEntries(index + 1)]
50
+
51
+ const entries = createEntries(0)
52
+
53
+ /** @type {(separator: string) => ExclusiveScan<string, string>} */
54
+ const join = separator => ['', value => [value, scan(op.join(separator))(value)]]
55
+
56
+ const sum = exclusiveScan(op.addition)(0)
57
+
58
+ /** @type {(a: number) => () => number} */
59
+ const counter = a => () => a + 1
60
+
61
+ const length = exclusiveScan(counter)(0)
62
+
63
+ /**
64
+ * @template T
65
+ * @template R
66
+ * @typedef {(value: T) => R} Func
67
+ */
68
+
69
+ /** @type {<T, R, X>(flatMap: (f: Func<T, readonly[R]>) => X) => (f: Func<T, R>) =>X} */
70
+ const map = flatMap => f => flatMap(x => [f(x)])
71
+
72
+ /** @type {<T, X>(flatMap: (f: Func<T, readonly[T]|[]>) => X) => (f: Func<T, boolean>) =>X} */
73
+ const filter = flatMap => f => flatMap(x => f(x) ? [x] : [])
74
+
75
+ module.exports = {
76
+ /** @readonly */
77
+ exclusiveScan,
78
+ /** @readonly */
79
+ scan,
80
+ /** @readonly */
81
+ join,
82
+ /** @readonly */
83
+ sum,
84
+ /** @readonly */
85
+ length,
86
+ /** @readonly */
87
+ entries,
88
+ /** @readonly */
89
+ map,
90
+ /** @readonly */
91
+ filter,
92
+ }
@@ -0,0 +1,43 @@
1
+ const seq = require('.')
2
+ const { sum } = require('./operator')
3
+
4
+ /** @type {<T>(input: seq.Sequence<T>) => void} */
5
+ const print = input => {
6
+ let i = input
7
+ while (true) {
8
+ const result = seq.next(i)
9
+ if (result === undefined) { return }
10
+ // console.log(result[0])
11
+ i = result[1]
12
+ }
13
+ }
14
+
15
+ {
16
+ const big = seq.fromArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 42, 60])
17
+ const list0 = seq.fromArray([0, 1, 2, 3])
18
+ const list1 = seq.flatMap(x => seq.fromArray([x, x * 2, x * 3]))(list0)
19
+ const list2 = seq.concat(list0)(list0)
20
+ const list3 = seq.exclusiveScan(sum)(list0)
21
+ const r = seq.find(x => x === 42)(big)
22
+ if (seq.every(x => x > 0)(big) !== true) { throw 'x'}
23
+ if (seq.every(x => x < 20)(big) !== false) { throw 'x' }
24
+ if (seq.some(x => x > 100)(big) !== false) { throw 'x' }
25
+ if (seq.some(x => x > 50)(big) !== true) { throw 'x' }
26
+ if (seq.first(seq.drop(16)(big)) !== 42) { throw 'drop'}
27
+ {
28
+ let x = big
29
+ for (let i = 0; i < 1_000_000; ++i) {
30
+ x = seq.concat(seq.empty)(x)
31
+ }
32
+ const r = seq.next(x)
33
+ // print(x)
34
+ }
35
+ {
36
+ let x = big
37
+ for (let i = 0; i < 1_000_000; ++i) {
38
+ x = seq.concat(x)(seq.one(i))
39
+ }
40
+ const r = seq.next(x)
41
+ // print(x)
42
+ }
43
+ }
package/test.js CHANGED
@@ -1,6 +1,6 @@
1
1
  const i = require('./')
2
2
 
3
- require('./sequence/list/test')
3
+ require('./sequence/test')
4
4
  require('./btree/test')
5
5
  require('./sequence/iterable/test')
6
6
  require('./sequence/asyncIterable/test')
@@ -1,305 +0,0 @@
1
- const array = require('../array')
2
- const base = require('..')
3
- const { pipe } = require('../../function')
4
- const { logicalNot, strictEqual } = require('../../function/operator')
5
-
6
- /**
7
- * @template T
8
- * @typedef {() => Result<T>} ListFunc
9
- */
10
-
11
- /**
12
- * @template T
13
- * @typedef {readonly [List<T>, List<T>]} Concat
14
- */
15
-
16
- /**
17
- * Use `next` function to get `first` and `tail` of the list.
18
- *
19
- * Please note that the list also contains `Concat<T>. We need this as
20
- * a workaround because modern JavaScript implementations don't support
21
- * ES6 TCO (Tail Call Optimization). Without this wotkaround we may have
22
- * a stack overflow if a list contains a lot of concateneted lists.
23
- *
24
- * @template T
25
- * @typedef { ListFunc<T> | Concat<T>} List
26
- */
27
-
28
- /**
29
- * @template T
30
- * @typedef {FirstAndTail<T>|undefined} Result<T>
31
- */
32
-
33
- /**
34
- * @template T
35
- * @typedef {array.Tuple2<T, List<T>>} FirstAndTail
36
- */
37
-
38
- const empty = () => undefined
39
-
40
- /** @type {<F, T>(a: readonly[F, List<T>]) => (b: List<T>) => readonly[F, List<T>]} */
41
- const norm = ([a0, a1]) => b => [a0, [a1, b]]
42
-
43
- /** @type {<T>(list: List<T>) => Result<T>} */
44
- const next = list => {
45
- let i = list
46
- while (true) {
47
- if (typeof i === 'function') { return i() }
48
- const [a, b] = i
49
- if (typeof a === 'function') {
50
- const result = a()
51
- if (result !== undefined) {
52
- return norm(result)(b)
53
- }
54
- i = b
55
- } else {
56
- i = norm(a)(b)
57
- }
58
- }
59
- }
60
-
61
- /** @type {<T>(list: List<T>) => T|undefined} */
62
- const first = list => {
63
- const result = next(list)
64
- if (result === undefined) { return undefined }
65
- return result[0]
66
- }
67
-
68
- /**
69
- * @template T
70
- * @template R
71
- * @typedef {(list: List<T>) => List<R>} ListMap
72
- */
73
-
74
- /**
75
- * @template T
76
- * @template R
77
- * @typedef {(list: List<T>) => R} ListReduce
78
- */
79
-
80
- /** @type {<T>(first: T) => List<T>} */
81
- const one = first => () => [first, empty]
82
-
83
- /** @type {<T>(array: array.Array<T>) => List<T>} */
84
- const fromArray = a => {
85
- /** @typedef {typeof a extends array.Array<infer T> ? T : never} T */
86
- /** @type {(index: number) => List<T>} */
87
- const at = index => () => {
88
- const result = array.at(index)(a)
89
- if (result === undefined) { return undefined }
90
- return [result[0], at(index + 1)]
91
- }
92
- return at(0)
93
- }
94
-
95
- /** @type {<T>(list0: List<T>) => ListMap<T, T>} */
96
- const concat = a => b => [a, b]
97
-
98
- /** @type {<T, R>(f: (value: T) => List<R>) => ListMap<T, R>} */
99
- const flatMap = f => input => () => {
100
- let i = input
101
- while (true) {
102
- const result = next(i)
103
- if (result === undefined) { return undefined }
104
- const [first, tail] = result
105
- const firstResult = next(f(first))
106
- if (firstResult !== undefined) {
107
- const [firstFirst, firstTail] = firstResult
108
- return [firstFirst, concat(firstTail)(flatMap(f)(tail))]
109
- }
110
- i = tail
111
- }
112
- }
113
-
114
- /** @type {<T>(list: List<List<T>>) => List<T>} */
115
- const flat = flatMap(i => i)
116
-
117
- /** @type {<T, R>(f: (value: T) => R) => ListMap<T, R>} */
118
- const map = f => flatMap(i => one(f(i)))
119
-
120
- /** @type {<T>(f: (value: T) => boolean) => ListMap<T, T>} */
121
- const filter = f => flatMap(i => f(i) ? one(i) : empty)
122
-
123
- /** @type {<T, R>(f: (value: T) => R|undefined) => (value: T) => List<R>} */
124
- const filterMapFunc = f => i => {
125
- const result = f(i)
126
- if (result === undefined) { return empty }
127
- return one(result)
128
- }
129
-
130
- /** @type {<T, R>(f: (value: T) => R|undefined) => ListMap<T, R>} */
131
- const filterMap = f => flatMap(filterMapFunc(f))
132
-
133
- /** @type {<T, R>(s: base.Scan<T, R>) => ListMap<T, R>} */
134
- const scan = s => input => () => {
135
- const result = next(input)
136
- if (result === undefined) {
137
- return result
138
- }
139
- const [first, tail] = result
140
- const [newFirst, newS] = s(first)
141
- return [newFirst, scan(newS)(tail)]
142
- }
143
-
144
- /** @type {<T, R>(s: base.ExclusiveScan<T, R>) => ListMap<T, R>} */
145
- const exclusiveScan = ([first, s]) => input => () => [first, scan(s)(input)]
146
-
147
- /** @type {<T>(def: T) => (input: List<T>) => T} */
148
- const last = def => input => {
149
- let r = def
150
- let i = input
151
- while (true) {
152
- const result = next(i)
153
- if (result === undefined) {
154
- return r
155
- }
156
- r = result[0]
157
- i = result[1]
158
- }
159
- }
160
-
161
- /** @type {<T, R>(s: base.ExclusiveScan<T, R>) => (input: List<T>) => R} */
162
- const reduce = ([first, s]) => input => last(first)(scan(s)(input))
163
-
164
- const entries = scan(base.entries)
165
-
166
- const sum = reduce(base.sum)
167
-
168
- const length = reduce(base.length)
169
-
170
- const join = pipe(base.join)(reduce)
171
-
172
- /** @type {<T>(f: (value: T) => boolean) => ListMap<T, T>} */
173
- const takeWhile = f => input => () => {
174
- const result = next(input)
175
- if (result === undefined || !f(result[0])) { return undefined }
176
- return result
177
- }
178
-
179
- /** @type {(n: number) => <T>(input: List<T>) => List<T>} */
180
- const drop = n => input => () => {
181
- let iN = n
182
- let iInput = input
183
- while (true) {
184
- const result = next(iInput)
185
- if (iN <= 0 || result === undefined) { return result }
186
- iN = iN - 1
187
- iInput = result[1]
188
- }
189
- }
190
-
191
- /** @type {(n: number) => <T>(input: List<T>) => T|undefined} */
192
- const at = n => input => first(drop(n)(input))
193
-
194
- /** @type {<T>(f: (value: T) => boolean) => ListReduce<T, T|undefined>} */
195
- const find = f => input => first(filter(f)(input))
196
-
197
- /** @type {<T>(f: (value: T) => boolean) => ListReduce<T, boolean>} */
198
- const some = f => input => find(x => x)(map(f)(input)) !== undefined
199
-
200
- /** @type {<T>(value: T) => ListReduce<T, boolean>} */
201
- const includes = value => some(strictEqual(value))
202
-
203
- /** @type {<T>(f: (value: T) => boolean) => ListReduce<T, boolean>} */
204
- const every = f => input => !some(pipe(f)(logicalNot))(input)
205
-
206
- /** @type {<T>(list: List<T>) => Iterable<T>} */
207
- const iterable = list => ({
208
- *[Symbol.iterator]() {
209
- let i = list
210
- while (true) {
211
- const result = next(i)
212
- if (result === undefined) { return }
213
- yield result[0]
214
- i = result[1]
215
- }
216
- }
217
- })
218
-
219
- /** @type {<T>(list: List<T>) => AsyncIterable<T>} */
220
- const asyncIterable = list => ({
221
- async *[Symbol.asyncIterator]() {
222
- let i = list
223
- while (true) {
224
- const result = next(i)
225
- if (result === undefined) { return }
226
- yield result[0]
227
- i = result[1]
228
- }
229
- }
230
- })
231
-
232
- /** @type {<A>(a: List<A>) => <B>(b: List<B>) => List<array.Tuple2<A, B>>} */
233
- const zip = a => b => () => {
234
- const resultA = next(a)
235
- if (resultA === undefined) { return undefined }
236
- const resultB = next(b)
237
- if (resultB === undefined) { return undefined }
238
- return [[resultA[0], resultB[0]], zip(resultA[1])(resultB[1])]
239
- }
240
-
241
- /** @type {<T>(list: List<T>) => readonly T[]} */
242
- const toArray = input => Array.from(iterable(input))
243
-
244
- module.exports = {
245
- /** @readonly */
246
- next,
247
- /** @readonly */
248
- one,
249
- /** @readonly */
250
- empty,
251
- /** @readonly */
252
- at,
253
- /** @readonly */
254
- concat,
255
- /** @readonly */
256
- first,
257
- /** @readonly */
258
- fromArray,
259
- /** @readonly */
260
- toArray,
261
- /** @readonly */
262
- iterable,
263
- /** @readonly */
264
- asyncIterable,
265
- /** @readonly */
266
- flatMap,
267
- /** @readonly */
268
- flat,
269
- /** @readonly */
270
- map,
271
- /** @readonly */
272
- filter,
273
- /** @readonly */
274
- filterMap,
275
- /** @readonly */
276
- scan,
277
- /** @readonly */
278
- exclusiveScan,
279
- /** @readonly */
280
- last,
281
- /** @readonly */
282
- reduce,
283
- /** @readonly */
284
- entries,
285
- /** @readonly */
286
- sum,
287
- /** @readonly */
288
- join,
289
- /** @readonly */
290
- length,
291
- /** @readonly */
292
- drop,
293
- /** @readonly */
294
- find,
295
- /** @readonly */
296
- takeWhile,
297
- /** @readonly */
298
- some,
299
- /** @readonly */
300
- every,
301
- /** @readonly */
302
- includes,
303
- /** @readonly */
304
- zip,
305
- }
@@ -1,43 +0,0 @@
1
- const list = require('.')
2
- const { sum } = require('..')
3
-
4
- /** @type {<T>(l: list.List<T>) => void} */
5
- const print = a => {
6
- let i = a
7
- while (true) {
8
- const result = list.next(i)
9
- if (result === undefined) { return }
10
- // console.log(result[0])
11
- i = result[1]
12
- }
13
- }
14
-
15
- {
16
- const big = list.fromArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 42, 60])
17
- const list0 = list.fromArray([0, 1, 2, 3])
18
- const list1 = list.flatMap(x => list.fromArray([x, x * 2, x * 3]))(list0)
19
- const list2 = list.concat(list0)(list0)
20
- const list3 = list.exclusiveScan(sum)(list0)
21
- const r = list.find(x => x === 42)(big)
22
- if (list.every(x => x > 0)(big) !== true) { throw 'x'}
23
- if (list.every(x => x < 20)(big) !== false) { throw 'x' }
24
- if (list.some(x => x > 100)(big) !== false) { throw 'x' }
25
- if (list.some(x => x > 50)(big) !== true) { throw 'x' }
26
- if (list.first(list.drop(16)(big)) !== 42) { throw 'drop'}
27
- {
28
- let x = big
29
- for (let i = 0; i < 1_000_000; ++i) {
30
- x = list.concat(list.empty)(x)
31
- }
32
- const r = list.next(x)
33
- // print(x)
34
- }
35
- {
36
- let x = big
37
- for (let i = 0; i < 1_000_000; ++i) {
38
- x = list.concat(x)(list.one(i))
39
- }
40
- const r = list.next(x)
41
- // print(x)
42
- }
43
- }