functionalscript 0.0.168 → 0.0.178

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,4 +1,6 @@
1
1
  const { index3, index5 } = require('../cmp')
2
+ const list = require('../sequence/list')
3
+ const { pipe } = require('../function')
2
4
 
3
5
  /**
4
6
  * @template T
@@ -12,24 +14,24 @@ const { index3, index5 } = require('../cmp')
12
14
 
13
15
  /**
14
16
  * @template T
15
- * @typedef {import('../array').Array1<T>} Array1
17
+ * @typedef {import('../sequence/array').Array1<T>} Array1
16
18
  */
17
19
 
18
20
  /**
19
21
  * @template T
20
- * @typedef {import('../array').Array2<T>} Array2
22
+ * @typedef {import('../sequence/array').Array2<T>} Array2
21
23
  */
22
24
 
23
25
  /**
24
26
  * @template T
25
- * @typedef {import('../array').Array3<T>} Array3
27
+ * @typedef {import('../sequence/array').Array3<T>} Array3
26
28
  */
27
29
 
28
- /** @typedef {import('../array').Index2} Index2 */
30
+ /** @typedef {import('../sequence/array').Index2} Index2 */
29
31
 
30
- /** @typedef {import('../array').Index3} Index3 */
32
+ /** @typedef {import('../sequence/array').Index3} Index3 */
31
33
 
32
- /** @typedef {import('../array').Index5} Index5 */
34
+ /** @typedef {import('../sequence/array').Index5} Index5 */
33
35
 
34
36
  //
35
37
 
@@ -45,17 +47,17 @@ const { index3, index5 } = require('../cmp')
45
47
 
46
48
  /**
47
49
  * @template T
48
- * @typedef {readonly [TNode<T>, T, TNode<T>]} Branch3
50
+ * @typedef {readonly [Node<T>, T, Node<T>]} Branch3
49
51
  */
50
52
 
51
53
  /**
52
54
  * @template T
53
- * @typedef {readonly [TNode<T>, T, TNode<T>, T, TNode<T>]} Branch5
55
+ * @typedef {readonly [Node<T>, T, Node<T>, T, Node<T>]} Branch5
54
56
  */
55
57
 
56
58
  /**
57
59
  * @template T
58
- * @typedef { Leaf1<T> | Leaf2<T> | Branch3<T> | Branch5<T>} TNode
60
+ * @typedef { Leaf1<T> | Leaf2<T> | Branch3<T> | Branch5<T>} Node
59
61
  */
60
62
 
61
63
  /** @typedef {{ readonly done: false }} NotFoundDone */
@@ -75,7 +77,7 @@ const { index3, index5 } = require('../cmp')
75
77
 
76
78
  /**
77
79
  * @template T
78
- * @typedef {{ readonly replace: TNode<T> }} Replace
80
+ * @typedef {{ readonly replace: Node<T> }} Replace
79
81
  */
80
82
 
81
83
  /**
@@ -123,7 +125,7 @@ const { index3, index5 } = require('../cmp')
123
125
 
124
126
  /**
125
127
  * @template T
126
- * @typedef { readonly [TNode<T>, T, TNode<T>, T, TNode<T>, T, TNode<T>] } Branch7
128
+ * @typedef { readonly [Node<T>, T, Node<T>, T, Node<T>, T, Node<T>] } Branch7
127
129
  */
128
130
 
129
131
  /** @type {<T>(n: Branch7<T>) => Branch3<T>} */
@@ -131,7 +133,7 @@ const split = ([n0, v1, n2, v3, n4, v5, n6]) => [[n0, v1, n2], v3, [n4, v5, n6]]
131
133
 
132
134
  /**
133
135
  * @type {<T>(overflow: (o: Branch3<T>) => Result<T>) =>
134
- * (replace: (r: TNode<T>) => TNode<T>) =>
136
+ * (replace: (r: Node<T>) => Node<T>) =>
135
137
  * (result: Result<T>) =>
136
138
  * Result<T>}
137
139
  */
@@ -143,7 +145,7 @@ const merge = overflow => replace => result => {
143
145
 
144
146
  /**
145
147
  * @type {<T>(overflow: (o: Branch3<T>) => Branch5<T>) =>
146
- * (replace: (r: TNode<T>) => Branch3<T>) =>
148
+ * (replace: (r: Node<T>) => Branch3<T>) =>
147
149
  * (result: Result<T>) =>
148
150
  * Result<T>}
149
151
  */
@@ -151,19 +153,19 @@ const merge2 = overflow => merge(o => ({ replace: overflow(o) }))
151
153
 
152
154
  /**
153
155
  * @type {<T>(overflow: (o: Branch3<T>) => Branch7<T>) =>
154
- * (replace: (r: TNode<T>) => Branch5<T>) =>
156
+ * (replace: (r: Node<T>) => Branch5<T>) =>
155
157
  * (result: Result<T>) =>
156
158
  * Result<T>}
157
159
  */
158
160
  const merge3 = overflow => merge(o => ({ overflow: split(overflow(o)) }))
159
161
 
160
- /** @type {(visitor: Visitor) => <T>(cmp: Cmp<T>) => (init: Lazy<T>) => (node: TNode<T>) => Result<T>} */
162
+ /** @type {(visitor: Visitor) => <T>(cmp: Cmp<T>) => (init: Lazy<T>) => (node: Node<T>) => Result<T>} */
161
163
  const visit = ({ found, notFound }) => cmp => {
162
164
  const i3 = index3(cmp)
163
165
  const i5 = index5(cmp)
164
166
  return init => {
165
167
  /** @typedef {typeof cmp extends Cmp<infer T> ? T : never} T*/
166
- /** @type {(node: TNode<T>) => Result<T>} */
168
+ /** @type {(node: Node<T>) => Result<T>} */
167
169
  const f = node => {
168
170
  switch (node.length) {
169
171
  case 1: {
@@ -255,7 +257,7 @@ const notFoundGet = {
255
257
  leaf2_right: notFound,
256
258
  }
257
259
 
258
- /** @type { <T>(_: TNode<T>) => Replace<T> } */
260
+ /** @type { <T>(_: Node<T>) => Replace<T> } */
259
261
  const replace = node => ({ replace: node })
260
262
 
261
263
  /** @type {Found} */
@@ -304,7 +306,7 @@ const replaceVisitor = {
304
306
  notFound: notFoundGet,
305
307
  }
306
308
 
307
- /** @type {<T>(_: TNode<T>) => Iterable<T>} */
309
+ /** @type {<T>(_: Node<T>) => Iterable<T>} */
308
310
  const values = node => ({
309
311
  *[Symbol.iterator]() {
310
312
  switch (node.length) {
@@ -330,12 +332,43 @@ const values = node => ({
330
332
  }
331
333
  })
332
334
 
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>} */
339
+ const valuesList = node => () => {
340
+ const f = () => {
341
+ switch (node.length) {
342
+ case 1: case 2: { return list.fromArray(node) }
343
+ case 3: {
344
+ return flatArray(
345
+ valuesList(node[0]),
346
+ list.one(node[1]),
347
+ valuesList(node[2])
348
+ )
349
+ }
350
+ default: {
351
+ return flatArray(
352
+ valuesList(node[0]),
353
+ list.one(node[1]),
354
+ valuesList(node[2]),
355
+ list.one(node[3]),
356
+ valuesList(node[4])
357
+ )
358
+ }
359
+ }
360
+ }
361
+ return f()()
362
+ }
363
+
333
364
  module.exports = {
365
+ /** @readonly */
366
+ valuesList,
334
367
  /** @readonly */
335
368
  values,
336
369
  /**
337
370
  * @readonly
338
- * @type { <T>(cmp: Cmp<T>) => (node: TNode<T>) => T|undefined }
371
+ * @type { <T>(cmp: Cmp<T>) => (node: Node<T>) => T|undefined }
339
372
  */
340
373
  getVisitor: cmp => node => {
341
374
  const result = visit(getVisitor)(cmp)(() => { throw '' })(node)
package/btree/test.js ADDED
@@ -0,0 +1,33 @@
1
+ const btree = require('.')
2
+ const { setVisitor, valuesList } = btree
3
+ const { cmp } = require('../cmp')
4
+
5
+ /** @type {(node: btree.Node<string>) => (value: string) => btree.Node<string>} */
6
+ const set = node => value => {
7
+ const result = setVisitor(cmp(value))(() => value)(node)
8
+ if ('replace' in result) { return result.replace }
9
+ if ('overflow' in result) { return result.overflow }
10
+ return node
11
+ }
12
+
13
+ const test = () => {
14
+ /** @type {btree.Node<string>} */
15
+ let node = ['a']
16
+ node = set(node)('b')
17
+ node = set(node)('c')
18
+ node = set(node)('d')
19
+ node = set(node)('e')
20
+ node = set(node)('f')
21
+ //
22
+ {
23
+ /** @type {import('../sequence/list').Result<string>} */
24
+ let result = valuesList(node)()
25
+ while (result !== undefined) {
26
+ const t = result[0]
27
+ console.log(t)
28
+ result = result[1]()
29
+ }
30
+ }
31
+ }
32
+
33
+ test()
package/cmp/index.js CHANGED
@@ -1,9 +1,9 @@
1
- /** @typedef {import('../array').Index3} Index3 */
2
- /** @typedef {import('../array').Index5} Index5 */
1
+ /** @typedef {import('../sequence/array').Index3} Index3 */
2
+ /** @typedef {import('../sequence/array').Index5} Index5 */
3
3
 
4
4
  /**
5
5
  * @template T
6
- * @typedef {import('../array').Array2<T>} Array2
6
+ * @typedef {import('../sequence/array').Array2<T>} Array2
7
7
  */
8
8
 
9
9
  /** @typedef {-1|0|1} Sign */
@@ -22,9 +22,14 @@ const index5 = cmp => ([v0, v1]) => {
22
22
  return /** @type {Index5} */ (i <= 0 ? i + 1 : cmp(v1) + 3)
23
23
  }
24
24
 
25
+ /** @type {(a: string) => (b: string) => Sign} */
26
+ const cmp = a => b => a < b ? -1 : a === b ? 0 : 1
27
+
25
28
  module.exports = {
26
29
  /** @readonly */
27
30
  index3,
28
31
  /** @readonly */
29
32
  index5,
30
- }
33
+ /** @readonly */
34
+ cmp,
35
+ }
package/function/index.js CHANGED
@@ -13,21 +13,6 @@ const pipe = g => f => x => f(g(x))
13
13
  /** @type {<T>(value: T) => T} */
14
14
  const id = value => value
15
15
 
16
- /**
17
- * @template I
18
- * @template O
19
- * @typedef {{
20
- * readonly pipe: <R>(f: Func<O, R>) => Pipe<I, R>
21
- * readonly call: Func<I, O>
22
- * }} Pipe
23
- */
24
-
25
- /** @type {<I, O>(f: Func<I, O>) => Pipe<I, O>} */
26
- const pipex = call => ({
27
- pipe: f => pipex(pipe(call)(f)),
28
- call,
29
- })
30
-
31
16
  module.exports = {
32
17
  /** @readonly */
33
18
  id,
@@ -35,6 +20,4 @@ module.exports = {
35
20
  pipe,
36
21
  /** @readonly */
37
22
  combine,
38
- /** @readonly */
39
- pipex,
40
23
  }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @template R
3
+ * @template T
4
+ * @typedef {(prior: R) => (value: T) => R} BinaryOperator
5
+ */
6
+
7
+ /** @type {(separator: string) => BinaryOperator<string, string>} */
8
+ const join = separator => prior => value => `${prior}${separator}${value}`
9
+
10
+ /** @type {(sum: number) => (value: number) => number} */
11
+ const addition = a => b => a + b
12
+
13
+ module.exports = {
14
+ /** @readonly */
15
+ join,
16
+ /** @readonly */
17
+ addition,
18
+ }
package/map/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const option = require("../option")
2
2
  const { getVisitor, setVisitor, values } = require("../btree")
3
+ const { cmp } = require("../cmp")
3
4
 
4
5
  /** @typedef {import("../cmp").Sign} Sign */
5
6
 
@@ -10,7 +11,7 @@ const { getVisitor, setVisitor, values } = require("../btree")
10
11
 
11
12
  /**
12
13
  * @template T
13
- * @typedef {import("../btree").TNode<T>} TNode
14
+ * @typedef {import("../btree").Node<T>} TNode
14
15
  */
15
16
 
16
17
  /**
@@ -34,13 +35,13 @@ const { getVisitor, setVisitor, values } = require("../btree")
34
35
  */
35
36
 
36
37
  /** @type {(a: string) => <T>(b: Entry<T>) => Sign} */
37
- const cmp = a => ([b]) => a < b ? -1 : a === b ? 0 : 1
38
+ const keyCmp = a => ([b]) => cmp(a)(b)
38
39
 
39
40
  /** @type {<T>(node: TNode<Entry<T>>) => Map<T>} */
40
41
  const create = root => ({
41
- get: name => option.map(([,value]) => value)(getVisitor(cmp(name))(root)),
42
+ get: name => option.map(([,value]) => value)(getVisitor(keyCmp(name))(root)),
42
43
  set: name => value => {
43
- const result = setVisitor(cmp(name))(() => [name, value])(root)
44
+ const result = setVisitor(keyCmp(name))(() => [name, value])(root)
44
45
  if ('replace' in result) { return create(result.replace) }
45
46
  if ('overflow' in result) { return create(result.overflow) }
46
47
  throw ''
@@ -1,8 +1,9 @@
1
- const array = require('../array')
1
+ const array = require('../sequence/array')
2
2
  const { pipe } = require('../function')
3
3
  const option = require('../option')
4
4
  const { head, last, splitLast, splitFirst } = array
5
- const iter = require('../iterable')
5
+ const iter = require('../sequence/iterable')
6
+ const seq = require('../sequence')
6
7
 
7
8
  /**
8
9
  * @template T
@@ -38,24 +39,22 @@ const iter = require('../iterable')
38
39
 
39
40
  /** @typedef {(_: string) => undefined|Package|Dependencies} Dependencies */
40
41
 
41
- /** @type {import('../sequence').Operation<string, undefined|Path, undefined|Path>} */
42
- const pathNormReduce = {
43
- merge: path => item =>
42
+ /** @type {seq.InclusiveScan<string, undefined|Path>} */
43
+ const pathNormReduce = seq.inclusiveScan
44
+ (path => item =>
44
45
  path === undefined ?
45
46
  undefined :
46
47
  ['', '.'].includes(item) ?
47
48
  path :
48
49
  item === '..' ?
49
50
  head(path) :
50
- [...path, item],
51
- init: [],
52
- result: s => s,
53
- }
51
+ [...path, item])
52
+ ([])
54
53
 
55
54
  /** @type {(_: Array<string>) => boolean} */
56
55
  const isRelative = localId => ['.', '..'].includes(localId[0])
57
56
 
58
- const pathNorm = iter.apply(pathNormReduce)
57
+ const pathNorm = iter.reduce(pathNormReduce)
59
58
 
60
59
  /** @type {(_: Package) => (_: Path) => Module|undefined} */
61
60
  const internal = pack => {
package/option/index.js CHANGED
@@ -3,10 +3,15 @@
3
3
  * @typedef {T|undefined} Option
4
4
  */
5
5
 
6
- /** @type {<T, R>(_: (_: T) => R) => (_: T|undefined) => R|undefined} */
7
- const map = f => x => x === undefined ? undefined : f(x)
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)
8
11
 
9
12
  module.exports = {
10
13
  /** @readonly */
11
14
  map,
15
+ /** @readonly */
16
+ match,
12
17
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.168",
3
+ "version": "0.0.178",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -0,0 +1,53 @@
1
+ # Sequences
2
+
3
+ Sequence types:
4
+
5
+ - Array
6
+ - List
7
+ - Iterable
8
+ - AsyncIterable
9
+
10
+ ## Functions
11
+
12
+ See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
13
+
14
+ - `length: Sequence<infer T> => number`
15
+ - `at: number => Sequence<infer T> = T`
16
+ - `concat: Sequence<infer T> => Sequence<T> => Sequence<T>`
17
+ - `entries: Sequence<infer T> => Sequence<[number, T]>`
18
+ - `every: (infer T => boolean) => Sequence<T> => boolean`
19
+ - `filter: (infer T => boolean) => Sequence<T> => Sequence<T>`
20
+ - `find: (infer T => boolean) => Sequence<T> => T`
21
+ - `findIndex: (infer T => boolean) => Sequence<T> => number`
22
+ - `flat: Sequence<Sequence<T>> => Sequence<T>`
23
+ - `flatMap: (infer T => Sequence<infer R>) => Sequence<T> => Sequence<R>`
24
+ - `includes: infer T => Sequence<T> => boolean`
25
+ - `indexOf: infer T => Sequence<T> => number`
26
+ - `join: string => Sequence<string> => string`
27
+ - `keys: Sequence<T> => Sequence<string>`
28
+ - `lastIndexOf: infer T => Sequence<T> => number`
29
+ - `map: (infer T => infer R) => Sequence<T> => Sequence<R>`
30
+ - `reduce: ...Scan<T, R> => Sequence<T> => R`
31
+ - `some: (infer T => boolean) => Sequence<T> => boolean`
32
+
33
+ ### Priority 2.
34
+
35
+ - `slice: number => number => Sequence<T> => Sequence<T>`
36
+ - `reduceRight: ...Scan<T, R> => Sequence<T> => R`
37
+ - `toLocalString: Locales => Sequence<T> => string`
38
+
39
+ ### Priority 3.
40
+
41
+ - `values: Sequence<infer T> => Sequence<T>`
42
+
43
+ ## Prohibited Array Operations
44
+
45
+ - `copyWithin`
46
+ - `fill`
47
+ - `pop`
48
+ - `push`
49
+ - `reverse`
50
+ - `shift`
51
+ - `sort`
52
+ - `splice`
53
+ - `unshift`
@@ -1,4 +1,4 @@
1
- const option = require('../option')
1
+ const option = require('../../option')
2
2
 
3
3
  /**
4
4
  * @template T
@@ -44,6 +44,11 @@ const option = require('../option')
44
44
  * @typedef {readonly [T, T, T, T, T]} Array5
45
45
  */
46
46
 
47
+ /**
48
+ * @template T
49
+ * @typedef {Array1<T>| Array2<T> | Array3<T> | Array4<T> | Array5<T>} Array1_5
50
+ */
51
+
47
52
  /** @typedef {0|1|2|3|4} Index5 */
48
53
 
49
54
  /** @type {<T>(_: Array<T>) => Array<T>} */
@@ -80,7 +85,12 @@ const splitLast = a => {
80
85
  return option.map(split)(last(a))
81
86
  }
82
87
 
88
+ /** @type {(index: number) => <T>(a: Array<T>) => readonly[T]|undefined} */
89
+ const at = index => a => index < a.length ? [a[index]] : undefined
90
+
83
91
  module.exports = {
92
+ /** @readonly */
93
+ at,
84
94
  /** @readnly */
85
95
  first,
86
96
  /** @readonly */
@@ -0,0 +1,111 @@
1
+ const { pipe } = require('../../function')
2
+ const seq = require('..')
3
+
4
+ /**
5
+ * @template T
6
+ * @typedef {Promise<T>|T} PromiseOrValue
7
+ */
8
+
9
+ /**
10
+ * @template T
11
+ * @typedef {Iterable<T> | AsyncIterable<T>} AsyncOrSyncIterable
12
+ */
13
+
14
+ /** @type {<T>(c: AsyncOrSyncIterable<AsyncOrSyncIterable<T>>) => AsyncIterable<T>} */
15
+ const flat = c => ({
16
+ async *[Symbol.asyncIterator]() {
17
+ for await (const i of c) {
18
+ yield* i
19
+ }
20
+ }
21
+ })
22
+
23
+ /** @type {<T, R>(f: (value: T) => AsyncOrSyncIterable<R>) => (c: AsyncOrSyncIterable<T>) => AsyncIterable<R>} */
24
+ const flatMap = f => c => ({
25
+ async *[Symbol.asyncIterator]() {
26
+ for await (const i of c) {
27
+ yield* await f(i)
28
+ }
29
+ }
30
+ })
31
+
32
+ /** @type {<T, R>(f: (value: T) => R) => (c: AsyncOrSyncIterable<T>) => AsyncIterable<R>} */
33
+ const map = seq.map(flatMap)
34
+
35
+ /** @type {<T>(f: (value: T) => boolean) => (c: AsyncOrSyncIterable<T>) => AsyncOrSyncIterable<T>} */
36
+ const filter = seq.filter(flatMap)
37
+
38
+ /** @type {<T>(a: AsyncOrSyncIterable<T>) => (b: AsyncOrSyncIterable<T>) => AsyncIterable<T>} */
39
+ const concat = a => b => ({
40
+ async *[Symbol.asyncIterator]() {
41
+ yield* a
42
+ yield* b
43
+ }
44
+ })
45
+
46
+ /** @type {<T, R>(s: seq.Scan<T, R>) => (c: AsyncOrSyncIterable<T>) => AsyncIterable<R>} */
47
+ const scan = s => c => ({
48
+ async *[Symbol.asyncIterator]() {
49
+ let next = s
50
+ for await (const i of c) {
51
+ const result = next(i)
52
+ next = result[1]
53
+ yield result[0]
54
+ }
55
+ }
56
+ })
57
+
58
+ /** @type {<T, R>(s: seq.InclusiveScan<T, R>) => (c: AsyncOrSyncIterable<T>) => AsyncIterable<R>} */
59
+ const inclusiveScan = ([first, s]) => c => concat([first])(scan(s)(c))
60
+
61
+ /** @type {<T, R>(is: seq.InclusiveScan<T, R>) => (c: AsyncOrSyncIterable<T>) => Promise<R>} */
62
+ const reduce = ([first, s]) => async c => {
63
+ let next = first
64
+ for await (const i of scan(s)(c)) {
65
+ next = i
66
+ }
67
+ return next
68
+ }
69
+
70
+ const sum = reduce(seq.sum)
71
+
72
+ const join = pipe(seq.join)(reduce)
73
+
74
+ const length = reduce(seq.length)
75
+
76
+ /** @type {<T>(f: (value: T) => boolean) => (c: AsyncOrSyncIterable<T>) => AsyncIterable<T>} */
77
+ const takeWhile = f => c => ({
78
+ async *[Symbol.asyncIterator]() {
79
+ for await (const i of c) {
80
+ if (!f(i)) { return }
81
+ yield i
82
+ }
83
+ }
84
+ })
85
+
86
+ module.exports = {
87
+ /** @readonly */
88
+ concat,
89
+ /** @readonly */
90
+ flat,
91
+ /** @readonly */
92
+ map,
93
+ /** @readonly */
94
+ filter,
95
+ /** @readonly */
96
+ flatMap,
97
+ /** @readonly */
98
+ reduce,
99
+ /** @readonly */
100
+ sum,
101
+ /** @readonly */
102
+ length,
103
+ /** @readonly */
104
+ join,
105
+ /** @readonly */
106
+ scan,
107
+ /** @readonly */
108
+ inclusiveScan,
109
+ /** @readonly */
110
+ takeWhile,
111
+ }
@@ -3,13 +3,13 @@ const { map, filter, flatMap, sum } = require('.')
3
3
  const test = async () => {
4
4
  {
5
5
  const a = [1, 2, 3]
6
- const m = map(async x => x * x)(a)
6
+ const m = map(x => x * x)(a)
7
7
  const result = await sum(m)
8
8
  if (result !== 14) { throw 'filter' }
9
9
  }
10
10
  {
11
11
  const a = [1, 2, 3, 4]
12
- const f = filter(async x => x !== 2)(a)
12
+ const f = filter(x => x !== 2)(a)
13
13
  const result = await sum(f)
14
14
  if (result !== 8) { throw 'filter' }
15
15
  }
package/sequence/index.js CHANGED
@@ -1,10 +1,10 @@
1
- const { todo } = require('../dev')
1
+ const op = require('../function/operator')
2
2
  const { id } = require('../function')
3
3
 
4
4
  /**
5
5
  * @template T0
6
6
  * @template T1
7
- * @typedef {import('../array').Tuple2<T0, T1>} Tuple2
7
+ * @typedef {import('./array').Tuple2<T0, T1>} Tuple2
8
8
  */
9
9
 
10
10
  /**
@@ -22,21 +22,12 @@ const { id } = require('../function')
22
22
  /**
23
23
  * @template T
24
24
  * @template R
25
- * @typedef {{
26
- * readonly scan: Scan<T, R>
27
- * readonly first: R
28
- * }} InclusiveScan
25
+ * @typedef {Tuple2<R, Scan<T, R>>} InclusiveScan
29
26
  */
30
27
 
31
- /**
32
- * @template R
33
- * @template T
34
- * @typedef {(prior: R) => (value: T) => R} BinaryOperator
35
- */
36
-
37
- /** @type {<R, T>(operator: BinaryOperator<R, T>) => (prior: R) => Scan<T, R>} */
38
- const operatorScan = operator => {
39
- /** @typedef {typeof operator extends BinaryOperator<infer R, infer T> ? [R, T] : never} RT */
28
+ /** @type {<R, T>(operator: op.BinaryOperator<R, T>) => (prior: R) => Scan<T, R>} */
29
+ const scan = operator => {
30
+ /** @typedef {typeof operator extends op.BinaryOperator<infer R, infer T> ? [R, T] : never} RT */
40
31
  /** @typedef {RT[0]} R */
41
32
  /** @typedef {RT[1]} T */
42
33
  /** @type {(prior: R) => Scan<T, R>} */
@@ -47,11 +38,8 @@ const operatorScan = operator => {
47
38
  return f
48
39
  }
49
40
 
50
- /** @type {<R, T>(operator: BinaryOperator<R, T>) => (first: R) => InclusiveScan<T, R>} */
51
- const inclusiveOperatorScan = operator => first => ({
52
- scan: operatorScan(operator)(first),
53
- first,
54
- })
41
+ /** @type {<R, T>(operator: op.BinaryOperator<R, T>) => (first: R) => InclusiveScan<T, R>} */
42
+ const inclusiveScan = operator => first => [first, scan(operator)(first)]
55
43
 
56
44
  /**
57
45
  * @template T
@@ -63,69 +51,40 @@ const createEntries = index => value => [[index, value], createEntries(index + 1
63
51
 
64
52
  const entries = createEntries(0)
65
53
 
66
- /** @type {(separator: string) => BinaryOperator<string, string>} */
67
- const joinOperation = separator => prior => value => `${prior}${separator}${value}`
68
-
69
54
  /** @type {(separator: string) => InclusiveScan<string, string>} */
70
- const join2 = separator => ({
71
- scan: value => [value, operatorScan(joinOperation(separator))(value)],
72
- first: ''
73
- })
74
-
75
- /** @type {(sum: number) => (value: number) => number} */
76
- const addition = a => b => a + b
55
+ const join = separator => ['', value => [value, scan(op.join(separator))(value)]]
77
56
 
78
- /** @type {InclusiveScan<number, number>} */
79
- const sum2 = inclusiveOperatorScan(addition)(0)
57
+ const sum = inclusiveScan(op.addition)(0)
80
58
 
81
- ////
59
+ const length = inclusiveScan(a => () => a + 1)(0)
82
60
 
83
61
  /**
84
- * @template I
85
- * @template S
86
- * @template O
87
- * @typedef {{
88
- * readonly merge: BinaryOperator<S, I>
89
- * readonly result: (state: S) => O
90
- * readonly init: S
91
- * }} Operation
62
+ * @template T
63
+ * @template R
64
+ * @typedef {(value: T) => R} Func
92
65
  */
93
66
 
94
- /** @type {(separator: string) => Operation<string, string|undefined, string>} */
95
- const join = separator => ({
96
- merge: s => i => s === undefined ? i : `${s}${separator}${i}`,
97
- init: undefined,
98
- result: s => s === undefined ? '' : s
99
- })
100
-
101
- /** @type {Operation<number, number, number>} */
102
- const sum = {
103
- merge: a => i => a + i,
104
- result: id,
105
- init: 0,
106
- }
67
+ /** @type {<T, R, X>(flatMap: (f: Func<T, readonly[R]>) => X) => (f: Func<T, R>) =>X} */
68
+ const map = flatMap => f => flatMap(x => [f(x)])
107
69
 
108
- /**
109
- * @type {{
110
- * readonly merge: (counter: number) => () => number
111
- * readonly result: (counter: number) => number
112
- * readonly init: number
113
- * }}
114
- */
115
- const size = {
116
- merge: counter => () => counter + 1,
117
- init: 0,
118
- result: id,
119
- }
70
+ /** @type {<T, X>(flatMap: (f: Func<T, readonly[T]|[]>) => X) => (f: Func<T, boolean>) =>X} */
71
+ const filter = flatMap => f => flatMap(x => f(x) ? [x] : [])
120
72
 
121
73
  module.exports = {
74
+ /** @readonly */
75
+ inclusiveScan,
76
+ /** @readonly */
77
+ scan,
122
78
  /** @readonly */
123
79
  join,
124
- join2,
125
80
  /** @readonly */
126
81
  sum,
127
82
  /** @readonly */
128
- size,
83
+ length,
129
84
  /** @readonly */
130
85
  entries,
86
+ /** @readonly */
87
+ map,
88
+ /** @readonly */
89
+ filter,
131
90
  }
@@ -0,0 +1,109 @@
1
+ const { pipe } = require('../../function')
2
+ const seq = require('..')
3
+
4
+ /** @type {<T>(a: Iterable<T>) => (b: Iterable<T>) => Iterable<T>} */
5
+ const concat = a => b => ({
6
+ *[Symbol.iterator]() {
7
+ yield* a
8
+ yield* b
9
+ }
10
+ })
11
+
12
+ /** @type {<T, R>(s: seq.Scan<T, R>) => (c: Iterable<T>) => Iterable<R>} */
13
+ const scan = s => c => ({
14
+ *[Symbol.iterator]() {
15
+ let next = s
16
+ for (const i of c) {
17
+ const result = next(i)
18
+ next = result[1]
19
+ yield result[0]
20
+ }
21
+ }
22
+ })
23
+
24
+ /** @type {<T, R>(s: seq.InclusiveScan<T, R>) => (c: Iterable<T>) => Iterable<R>} */
25
+ const inclusiveScan = ([first, s]) => c => concat([first])(scan(s)(c))
26
+
27
+ /** @type {<T, R>(s: seq.InclusiveScan<T, R>) => (c: Iterable<T>) => R} */
28
+ const reduce = ([first, s]) => c => {
29
+ let next = first
30
+ for (const i of scan(s)(c)) {
31
+ next = i
32
+ }
33
+ return next
34
+ }
35
+
36
+ const entries = scan(seq.entries)
37
+
38
+ const sum = reduce(seq.sum)
39
+
40
+ const length = reduce(seq.length)
41
+
42
+ const join = pipe(seq.join)(reduce)
43
+
44
+ /** @type {<T, R>(f: (value: T) => Iterable<R>) => (c: Iterable<T>) => Iterable<R>} */
45
+ const flatMap = f => c => ({
46
+ *[Symbol.iterator]() {
47
+ for (const i of c) {
48
+ yield* f(i)
49
+ }
50
+ }
51
+ })
52
+
53
+ /** @type {<T, R>(f: (value: T) => R) => (c: Iterable<T>) => Iterable<R>} */
54
+ const map = seq.map(flatMap)
55
+
56
+ /** @type {<T>(f: (value: T) => boolean) => (c: Iterable<T>) => Iterable<T>} */
57
+ const filter = seq.filter(flatMap)
58
+
59
+ /** @type {<T>(c: Iterable<Iterable<T>>) => Iterable<T>} */
60
+ const flat = flatMap(x => x)
61
+
62
+ /** @type {<T>(f: (value: T) => boolean) => (c: Iterable<T>) => Iterable<T>} */
63
+ const takeWhile = f => c => ({
64
+ *[Symbol.iterator]() {
65
+ for (const i of c) {
66
+ if (!f(i)) { return }
67
+ yield i
68
+ }
69
+ }
70
+ })
71
+
72
+ /** @type {<T>(_: (_: T) => boolean) => (_: Iterable<T>) => T|undefined} */
73
+ const find = f => c => {
74
+ for (const i of c) {
75
+ if (f(i)) {
76
+ return i
77
+ }
78
+ }
79
+ return undefined
80
+ }
81
+
82
+ module.exports = {
83
+ /** @readonly */
84
+ reduce,
85
+ /** @readonly */
86
+ join,
87
+ /** @readonly */
88
+ sum,
89
+ /** @readonly */
90
+ length,
91
+ /** @readonly */
92
+ entries,
93
+ /** @readonly */
94
+ scan,
95
+ /** @readonly */
96
+ inclusiveScan,
97
+ /** @readonly */
98
+ flatMap,
99
+ /** @readonly */
100
+ map,
101
+ /** @readonly */
102
+ filter,
103
+ /** @readonly */
104
+ flat,
105
+ /** @readonly */
106
+ takeWhile,
107
+ /** @readonly */
108
+ find,
109
+ }
@@ -1,5 +1,5 @@
1
1
  const i = require('.')
2
- const { pipe } = require('../function')
2
+ const { pipe } = require('../../function')
3
3
 
4
4
  {
5
5
  const r = i.sum([120, 300, 42])
@@ -0,0 +1,194 @@
1
+ const array = require('../array')
2
+ const option = require('../../option')
3
+ const base = require('..')
4
+ const { pipe } = require('../../function')
5
+ const { todo } = require('../../dev')
6
+
7
+ /**
8
+ * @template T
9
+ * @typedef {() => Result<T>} List
10
+ */
11
+
12
+ /**
13
+ * @template T
14
+ * @typedef {FirstAndTail<T>|undefined} Result<T>
15
+ */
16
+
17
+ /**
18
+ * @template T
19
+ * @typedef {array.Tuple2<T, List<T>>} FirstAndTail
20
+ */
21
+
22
+ const empty = () => undefined
23
+
24
+ /**
25
+ * @template T
26
+ * @template R
27
+ * @typedef {(list: List<T>) => List<R>} ListMap
28
+ */
29
+
30
+ /** @type {<T>(first: T) => ListMap<T, T>} */
31
+ const list = first => tail => () => [first, tail]
32
+
33
+ /** @type {<T>(first: T) => List<T>} */
34
+ const one = first => list(first)(empty)
35
+
36
+ /** @type {<T>(array: array.Array<T>) => List<T>} */
37
+ const fromArray = a => {
38
+ /** @typedef {typeof a extends array.Array<infer T> ? T : never} T */
39
+ /** @type {(index: number) => List<T>} */
40
+ const at = index => {
41
+ /** @type {(value: readonly [T]) => Result<T>} */
42
+ const result = ([value]) => list(value)(at(index + 1))()
43
+ return () => option.map(result)(array.at(index)(a))
44
+ }
45
+ return at(0)
46
+ }
47
+
48
+ /**
49
+ * Note: the function is not completly lazy.
50
+ * it calls `a()` as soon as `a` and `b` are provided.
51
+ * Othrewise we may have a stack overflow if a list
52
+ * contains a lot of concateneted empty lists.
53
+ * And we can't relay on ES6 TCO (Tail Call Optimization)
54
+ * because it's not supported by Chrome and Firefox.
55
+ * @type {<T>(list0: List<T>) => ListMap<T, T>}
56
+ */
57
+ const concat = a => b => {
58
+ const result = a()
59
+ if (result !== undefined) {
60
+ const [first, tail] = result
61
+ return () => [first, concat(tail)(b)]
62
+ }
63
+ return b
64
+ // /** @typedef {typeof a extends List<infer T> ? T : never} T */
65
+ // /** @type {(firstAntTail: FirstAndTail<T>) => Result<T>} */
66
+ // const defined = ([first, tail]) => [first, concat(tail)(b)]
67
+ // return option.match(defined)(b)(a())
68
+ }
69
+
70
+ /** @type {<T, R>(f: (value: T) => List<R>) => ListMap<T, R>} */
71
+ const flatMap = f => input => () => {
72
+ let i = input
73
+ while (true) {
74
+ const result = i()
75
+ if (result === undefined) { return undefined }
76
+ const [first, tail] = result
77
+ const firstResult = f(first)()
78
+ if (firstResult !== undefined) {
79
+ const [firstFirst, firstTail] = firstResult
80
+ return [firstFirst, concat(firstTail)(flatMap(f)(tail))]
81
+ }
82
+ i = tail
83
+ }
84
+ }
85
+
86
+ /** @type {<T>(list: List<List<T>>) => List<T>} */
87
+ const flat = flatMap(i => i)
88
+
89
+ /** @type {<T, R>(f: (value: T) => R) => ListMap<T, R>} */
90
+ const map = f => flatMap(i => one(f(i)))
91
+
92
+ /** @type {<T>(f: (value: T) => boolean) => ListMap<T, T>} */
93
+ const filter = f => flatMap(i => f(i) ? one(i) : empty)
94
+
95
+ /** @type {<T, R>(s: base.Scan<T, R>) => ListMap<T, R>} */
96
+ const scan = s => input => () => {
97
+ /** @typedef {typeof s extends base.Scan<infer T, infer R> ? [T, R] : never} TR */
98
+ /** @typedef {TR[0]} T */
99
+ /** @typedef {TR[1]} R */
100
+ /** @type {(firstAndTail: FirstAndTail<T>) => Result<R>} */
101
+ const defined = ([first, tail]) => {
102
+ const [newFirst, newS] = s(first)
103
+ return [newFirst, scan(newS)(tail)]
104
+ }
105
+ return option.map(defined)(input())
106
+ }
107
+
108
+ /** @type {<T, R>(s: base.InclusiveScan<T, R>) => ListMap<T, R>} */
109
+ const inclusiveScan = ([first, s]) => input => list(first)(scan(s)(input))
110
+
111
+ /** @type {<T>(def: T) => (input: List<T>) => T} */
112
+ const last = def => input => {
113
+ let i = input()
114
+ let r = def
115
+ while (i !== undefined) {
116
+ r = i[0]
117
+ i = i[1]()
118
+ }
119
+ return r
120
+ }
121
+
122
+ /** @type {<T, R>(s: base.InclusiveScan<T, R>) => (input: List<T>) => R} */
123
+ const reduce = s => input => last(s[0])(inclusiveScan(s)(input))
124
+
125
+ const entries = scan(base.entries)
126
+
127
+ const sum = reduce(base.sum)
128
+
129
+ const length = reduce(base.length)
130
+
131
+ const join = pipe(base.join)(reduce)
132
+
133
+ /** @type {<T>(f: (value: T) => boolean) => (input: List<T>) => T|undefined} */
134
+ const find = f => input => {
135
+ /** @typedef {typeof f extends (value: infer T) => boolean ? T : never} T */
136
+ /** @type {(result: FirstAndTail<T>) => T} */
137
+ const defined = ([first]) => first
138
+ return option.map(defined)(filter(f)(input)())
139
+ }
140
+
141
+ /**
142
+ * Note: probably, it's possible to implement using the `scan` concept.
143
+ * @type {<T>(list: List<T>) => Iterable<T>}
144
+ */
145
+ const iterable = list => ({
146
+ *[Symbol.iterator]() {
147
+ let result = list()
148
+ while (result !== undefined) {
149
+ yield result[0]
150
+ result = result[1]()
151
+ }
152
+ }
153
+ })
154
+
155
+ module.exports = {
156
+ /** @readonly */
157
+ list,
158
+ /** @readonly */
159
+ one,
160
+ /** @readonly */
161
+ empty,
162
+ /** @readonly */
163
+ concat,
164
+ /** @readonly */
165
+ fromArray,
166
+ /** @readonly */
167
+ iterable,
168
+ /** @readonly */
169
+ flatMap,
170
+ /** @readonly */
171
+ flat,
172
+ /** @readonly */
173
+ map,
174
+ /** @readonly */
175
+ filter,
176
+ /** @readonly */
177
+ scan,
178
+ /** @readonly */
179
+ inclusiveScan,
180
+ /** @readonly */
181
+ last,
182
+ /** @readonly */
183
+ reduce,
184
+ /** @readonly */
185
+ entries,
186
+ /** @readonly */
187
+ sum,
188
+ /** @readonly */
189
+ join,
190
+ /** @readonly */
191
+ length,
192
+ /** @readonly */
193
+ find,
194
+ }
@@ -0,0 +1,36 @@
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 (i !== undefined) {
8
+ console.log(i[0])
9
+ i = i[1]()
10
+ }
11
+ }
12
+
13
+ {
14
+ const big = list.fromArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 42, 60])
15
+ const list0 = list.fromArray([0, 1, 2, 3])
16
+ const list1 = list.flatMap(x => list.fromArray([x, x * 2, x * 3]))(list0)
17
+ const list2 = list.concat(list0)(list0)
18
+ const list3 = list.inclusiveScan(sum)(list0)
19
+ const r = list.find(x => x === 42)(big)
20
+ {
21
+ let x = big
22
+ for (let i = 0; i < 10000; ++i) {
23
+ x = list.concat(list.empty)(x)
24
+ }
25
+ const r = x()
26
+ print(x)
27
+ }
28
+ {
29
+ let x = big
30
+ for (let i = 0; i < 10000; ++i) {
31
+ x = list.concat(x)(list.empty)
32
+ }
33
+ const r = x()
34
+ print(x)
35
+ }
36
+ }
package/test.js CHANGED
@@ -1,7 +1,9 @@
1
1
  const i = require('./')
2
2
 
3
- require('./iterable/test')
4
- require('./async/iterable/test')
3
+ require('./sequence/list/test')
4
+ require('./btree/test')
5
+ require('./sequence/iterable/test')
6
+ require('./sequence/asyncIterable/test')
5
7
  require('./module-manager/test')
6
8
 
7
9
  /** @type {() => never} */
@@ -1,133 +0,0 @@
1
- const { pipe } = require('../../function')
2
- const seq = require('../../sequence')
3
-
4
- /**
5
- * @template T
6
- * @typedef {Promise<T>|T} PromiseOrValue
7
- */
8
-
9
- /**
10
- * @template T
11
- * @template R
12
- * @typedef {(f: (value: T) => PromiseOrValue<R>) => (c: AsyncIterable<T>) => AsyncIterable<R>} Map
13
- */
14
-
15
- /**
16
- * @template T
17
- * @typedef {Iterable<T> | AsyncIterable<T>} AnyIterable
18
- */
19
-
20
- /** @type {<T, R>(f: (value: T) => PromiseOrValue<R>) => (c: AnyIterable<T>) => AsyncIterable<R>} */
21
- const map = f => c => ({
22
- async *[Symbol.asyncIterator]() {
23
- for await (const i of c) {
24
- yield f(i)
25
- }
26
- }
27
- })
28
-
29
- /** @type {<T>(c: AnyIterable<AnyIterable<T>>) => AsyncIterable<T>} */
30
- const flatten = c => ({
31
- async *[Symbol.asyncIterator]() {
32
- for await (const i of c) {
33
- yield *i
34
- }
35
- }
36
- })
37
-
38
- /** @type {<T>(f: (value: T) => Promise<boolean>) => (c: AnyIterable<T>) => AnyIterable<T>} */
39
- const filter = f => c => ({
40
- async *[Symbol.asyncIterator]() {
41
- for await (const i of c) {
42
- if (await f(i)) {
43
- yield i
44
- }
45
- }
46
- }
47
- })
48
-
49
- /** @type {<T, R>(f: (value: T) => AnyIterable<R>) => (c: AnyIterable<T>) => AsyncIterable<R>} */
50
- const flatMap = f => pipe(map(f))(flatten)
51
-
52
- /**
53
- * @template A
54
- * @template T
55
- * @typedef {(accumulator: A) => (value: T) => PromiseOrValue<A>} Merge
56
- */
57
-
58
- /** @type {<A, T>(merge: Merge<A, T>) => (init: A) => (c: AnyIterable<T>) => Promise<A>} */
59
- const reduce = merge => init => async c => {
60
- let result = init
61
- for await (const i of c) {
62
- result = await merge(result)(i)
63
- }
64
- return result
65
- }
66
-
67
- /** @type {<T>(a: AnyIterable<T>) => (b: AnyIterable<T>) => AsyncIterable<T>} */
68
- const concat = a => b => ({
69
- async *[Symbol.asyncIterator]() {
70
- yield* a
71
- yield* b
72
- }
73
- })
74
-
75
- /** @type {<A, T>(merg: Merge<A, T>) => (init: A) => (c: AnyIterable<T>) => AsyncIterable<A>} */
76
- const exclusiveScan = merge => init => c => ({
77
- async *[Symbol.asyncIterator]() {
78
- let result = init
79
- for await (const i of c) {
80
- result = await merge(result)(i)
81
- yield result
82
- }
83
- }
84
- })
85
-
86
- /** @type {<T, R>(es: seq.Scan<T, R>) => (c: AnyIterable<T>) => AsyncIterable<R>} */
87
- const applyExclusiveScan = es => c => ({
88
- async *[Symbol.asyncIterator]() {
89
- let ies = es
90
- for await (const i of c) {
91
- const result = ies(i)
92
- ies = result[1]
93
- yield result[0]
94
- }
95
- }
96
- })
97
-
98
- /** @type {<A, T>(merge: Merge<A, T>) => (init: A) => (c: AnyIterable<T>) => AsyncIterable<A>} */
99
- const inclusiveScan = merge => init => c => concat([init])(exclusiveScan(merge)(init)(c))
100
-
101
- /** @type {<I, S, R>(op: seq.Operation<I, S, R>) => (_: AnyIterable<I>) => Promise<R>} */
102
- const apply = ({ merge, init, result }) => async c => result(await reduce(merge)(init)(c))
103
-
104
- const sum = apply(seq.sum)
105
-
106
- const join = pipe(seq.join)(apply)
107
-
108
- const size = apply(seq.size)
109
-
110
- module.exports = {
111
- /** @readonly */
112
- apply,
113
- /** @readonly */
114
- concat,
115
- /** @readonly */
116
- map,
117
- /** @readonly */
118
- filter,
119
- /** @readonly */
120
- flatMap,
121
- /** @readonly */
122
- reduce,
123
- /** @readonly */
124
- sum,
125
- /** @readonly */
126
- size,
127
- /** @readonly */
128
- join,
129
- /** @readonly */
130
- exclusiveScan,
131
- /** @readonly */
132
- inclusiveScan,
133
- }
package/iterable/index.js DELETED
@@ -1,116 +0,0 @@
1
- const { pipe } = require('../function')
2
- const seq = require('../sequence')
3
-
4
- /**
5
- * @template S
6
- * @template T
7
- * @typedef {(_: S) => (_: T) => S} Merge
8
- */
9
-
10
- /** @type {<T, R>(merge: Merge<R, T>) => (init: R) => (_: Iterable<T>) => R} */
11
- const reduce = merge => init => c => {
12
- let result = init
13
- for (const i of c) {
14
- result = merge(result)(i)
15
- }
16
- return result
17
- }
18
-
19
- /** @type {<T>(a: Iterable<T>) => (b: Iterable<T>) => Iterable<T>} */
20
- const concat = a => b => ({
21
- *[Symbol.iterator]() {
22
- yield *a
23
- yield *b
24
- }
25
- })
26
-
27
- /** @type {<A, T>(merge: Merge<A, T>) => (init: A) => (c: Iterable<T>) => Iterable<A>} */
28
- const exclusiveScan = merge => init => c => ({
29
- *[Symbol.iterator]() {
30
- let result = init
31
- for (const i of c) {
32
- result = merge(result)(i)
33
- yield result
34
- }
35
- }
36
- })
37
-
38
- /** @type {<A, T>(merge: Merge<A, T>) => (init: A) => (c: Iterable<T>) => Iterable<A>} */
39
- const inclusiveScan = merge => init => c => concat([init])(exclusiveScan(merge)(init)(c))
40
-
41
- /** @type {<T, R>(es: seq.Scan<T, R>) => (c: Iterable<T>) => Iterable<R>} */
42
- const applyScan = es => c => ({
43
- *[Symbol.iterator]() {
44
- let ies = es
45
- for (const i of c) {
46
- const result = ies(i)
47
- ies = result[1]
48
- yield result[0]
49
- }
50
- }
51
- })
52
-
53
- /** @type {<T, R>(is: seq.InclusiveScan<T, R>) => (c: Iterable<T>) => Iterable<R>} */
54
- const applyInclusiveScan = ({scan, first}) => c => concat([first])(applyScan(scan)(c))
55
-
56
- const entries = applyScan(seq.entries)
57
-
58
- /** @type {<I, S, R>(op: seq.Operation<I, S, R>) => (_: Iterable<I>) => R} */
59
- const apply = ({ merge, init, result }) => pipe(reduce(merge)(init))(result)
60
-
61
- const sum = apply(seq.sum)
62
-
63
- const size = apply(seq.size)
64
-
65
- const join = pipe(seq.join)(apply)
66
-
67
- /** @type {<T, R>(f: (value: T) => R) => (c: Iterable<T>) => Iterable<R>} */
68
- const map = f => c => ({
69
- *[Symbol.iterator]() {
70
- for (const i of c) {
71
- yield f(i)
72
- }
73
- }
74
- })
75
-
76
- /** @type {<T>(_: (_: T) => boolean) => (_: Iterable<T>) => T|undefined} */
77
- const find = f => c => {
78
- for (const i of c) {
79
- if (f(i)) {
80
- return i
81
- }
82
- }
83
- return undefined
84
- }
85
-
86
- module.exports = {
87
- /** @readonly */
88
- apply,
89
-
90
- /** @readonly */
91
- reduce,
92
-
93
- /** @readonly */
94
- join,
95
-
96
- /** @readonly */
97
- sum,
98
-
99
- /** @readonly */
100
- size,
101
-
102
- /** @readonly */
103
- entries,
104
-
105
- /** @readonly */
106
- map,
107
-
108
- /** @readonly */
109
- exclusiveScan,
110
-
111
- /** @readonly */
112
- inclusiveScan,
113
-
114
- /** @readonly */
115
- find,
116
- }