functionalscript 0.0.163 → 0.0.168

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/array/index.js CHANGED
@@ -17,6 +17,12 @@ const option = require('../option')
17
17
  * @typedef {readonly [T, T]} Array2
18
18
  */
19
19
 
20
+ /**
21
+ * @template T0
22
+ * @template T1
23
+ * @typedef {readonly [T0, T1]} Tuple2
24
+ */
25
+
20
26
  /** @typedef {0|1} Index2 */
21
27
 
22
28
  /**
@@ -1,13 +1,23 @@
1
- const { todo } = require('../../dev')
2
- const { pipe } = require('../../func')
3
- const mapReduce = require('../../map-reduce')
1
+ const { pipe } = require('../../function')
2
+ const seq = require('../../sequence')
4
3
 
5
4
  /**
6
5
  * @template T
7
6
  * @typedef {Promise<T>|T} PromiseOrValue
8
7
  */
9
8
 
10
- /** @type {<T, R>(f: (value: T) => PromiseOrValue<R>) => (c: AsyncIterable<T>) => AsyncIterable<R>} */
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>} */
11
21
  const map = f => c => ({
12
22
  async *[Symbol.asyncIterator]() {
13
23
  for await (const i of c) {
@@ -16,7 +26,7 @@ const map = f => c => ({
16
26
  }
17
27
  })
18
28
 
19
- /** @type {<T>(c: AsyncIterable<AsyncIterable<T>>) => AsyncIterable<T>} */
29
+ /** @type {<T>(c: AnyIterable<AnyIterable<T>>) => AsyncIterable<T>} */
20
30
  const flatten = c => ({
21
31
  async *[Symbol.asyncIterator]() {
22
32
  for await (const i of c) {
@@ -25,7 +35,7 @@ const flatten = c => ({
25
35
  }
26
36
  })
27
37
 
28
- /** @type {<T>(f: (value: T) => Promise<boolean>) => (c: AsyncIterable<T>) => AsyncIterable<T>} */
38
+ /** @type {<T>(f: (value: T) => Promise<boolean>) => (c: AnyIterable<T>) => AnyIterable<T>} */
29
39
  const filter = f => c => ({
30
40
  async *[Symbol.asyncIterator]() {
31
41
  for await (const i of c) {
@@ -36,7 +46,7 @@ const filter = f => c => ({
36
46
  }
37
47
  })
38
48
 
39
- /** @type {<T, R>(f: (value: T) => AsyncIterable<R>) => (c: AsyncIterable<T>) => AsyncIterable<R>} */
49
+ /** @type {<T, R>(f: (value: T) => AnyIterable<R>) => (c: AnyIterable<T>) => AsyncIterable<R>} */
40
50
  const flatMap = f => pipe(map(f))(flatten)
41
51
 
42
52
  /**
@@ -45,7 +55,7 @@ const flatMap = f => pipe(map(f))(flatten)
45
55
  * @typedef {(accumulator: A) => (value: T) => PromiseOrValue<A>} Merge
46
56
  */
47
57
 
48
- /** @type {<A, T>(f: Merge<A, T>) => (init: A) => (c: AsyncIterable<T>) => Promise<A>} */
58
+ /** @type {<A, T>(merge: Merge<A, T>) => (init: A) => (c: AnyIterable<T>) => Promise<A>} */
49
59
  const reduce = merge => init => async c => {
50
60
  let result = init
51
61
  for await (const i of c) {
@@ -54,49 +64,54 @@ const reduce = merge => init => async c => {
54
64
  return result
55
65
  }
56
66
 
57
- /** @type {<A, T>(f: Merge<A, T>) => (init: A) => (c: AsyncIterable<T>) => AsyncIterable<A>} */
58
- const exclusiveScan = reduceFn => init => c => ({
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 => ({
59
77
  async *[Symbol.asyncIterator]() {
60
78
  let result = init
61
79
  for await (const i of c) {
62
- result = await reduceFn(result)(i)
80
+ result = await merge(result)(i)
63
81
  yield result
64
82
  }
65
83
  }
66
84
  })
67
85
 
68
- /** @type {<A, T>(f: Merge<A, T>) => (init: A) => (c: AsyncIterable<T>) => AsyncIterable<A>} */
69
- const inclusiveScan = reduceFn => init => {
70
- const e = exclusiveScan(reduceFn)(init)
71
- return c => ({
72
- async *[Symbol.asyncIterator]() {
73
- yield init
74
- yield *e(c)
75
- }
76
- })
77
- }
78
-
79
- /** @type {<T>(iterable: Iterable<T>) => AsyncIterable<T>} */
80
- const cast = iterable => ({
86
+ /** @type {<T, R>(es: seq.Scan<T, R>) => (c: AnyIterable<T>) => AsyncIterable<R>} */
87
+ const applyExclusiveScan = es => c => ({
81
88
  async *[Symbol.asyncIterator]() {
82
- for (const i of iterable) {
83
- yield i
89
+ let ies = es
90
+ for await (const i of c) {
91
+ const result = ies(i)
92
+ ies = result[1]
93
+ yield result[0]
84
94
  }
85
95
  }
86
96
  })
87
97
 
88
- /** @type {<I, S, R>(op: mapReduce.Operation<I, S, R>) => (_: AsyncIterable<I>) => Promise<R>} */
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>} */
89
102
  const apply = ({ merge, init, result }) => async c => result(await reduce(merge)(init)(c))
90
103
 
91
- const sum = apply(mapReduce.sum)
104
+ const sum = apply(seq.sum)
92
105
 
93
- const join = pipe(mapReduce.join)(apply)
106
+ const join = pipe(seq.join)(apply)
107
+
108
+ const size = apply(seq.size)
94
109
 
95
110
  module.exports = {
96
111
  /** @readonly */
97
112
  apply,
98
113
  /** @readonly */
99
- cast,
114
+ concat,
100
115
  /** @readonly */
101
116
  map,
102
117
  /** @readonly */
@@ -108,6 +123,8 @@ module.exports = {
108
123
  /** @readonly */
109
124
  sum,
110
125
  /** @readonly */
126
+ size,
127
+ /** @readonly */
111
128
  join,
112
129
  /** @readonly */
113
130
  exclusiveScan,
@@ -1,21 +1,21 @@
1
- const { cast, map, filter, flatMap, sum } = require('.')
1
+ const { map, filter, flatMap, sum } = require('.')
2
2
 
3
3
  const test = async () => {
4
4
  {
5
- const a = cast([1, 2, 3])
5
+ const a = [1, 2, 3]
6
6
  const m = map(async x => x * x)(a)
7
7
  const result = await sum(m)
8
8
  if (result !== 14) { throw 'filter' }
9
9
  }
10
10
  {
11
- const a = cast([1, 2, 3, 4])
11
+ const a = [1, 2, 3, 4]
12
12
  const f = filter(async x => x !== 2)(a)
13
13
  const result = await sum(f)
14
14
  if (result !== 8) { throw 'filter' }
15
15
  }
16
16
  {
17
- const a = cast([1, 2])
18
- const f = flatMap(x => cast([x, x * x]))(a)
17
+ const a = [1, 2]
18
+ const f = flatMap(x => [x, x * x])(a)
19
19
  const result = await sum(f)
20
20
  if (result !== 8) { throw 'filter' }
21
21
  }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @template I
3
+ * @template O
4
+ * @typedef {(_: I) => O} Func
5
+ */
6
+
7
+ /** @type {<X, O>(f: Func<X, O>) => <I>(g: Func<I, X>) => Func<I, O>} */
8
+ const combine = f => g => x => f(g(x))
9
+
10
+ /** @type {<I, X>(g: Func<I, X>) => <O>(g: Func<X, O>) => Func<I, O>} */
11
+ const pipe = g => f => x => f(g(x))
12
+
13
+ /** @type {<T>(value: T) => T} */
14
+ const id = value => value
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
+ module.exports = {
32
+ /** @readonly */
33
+ id,
34
+ /** @readonly */
35
+ pipe,
36
+ /** @readonly */
37
+ combine,
38
+ /** @readonly */
39
+ pipex,
40
+ }
package/iterable/index.js CHANGED
@@ -1,7 +1,13 @@
1
- const { pipe } = require('../func')
2
- const mr = require('../map-reduce')
1
+ const { pipe } = require('../function')
2
+ const seq = require('../sequence')
3
3
 
4
- /** @type {<T, R>(merge: (_: R) => (_: T) => R) => (init: R) => (_: Iterable<T>) => R} */
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} */
5
11
  const reduce = merge => init => c => {
6
12
  let result = init
7
13
  for (const i of c) {
@@ -10,12 +16,53 @@ const reduce = merge => init => c => {
10
16
  return result
11
17
  }
12
18
 
13
- /** @type {<I, S, R>(op: mr.Operation<I, S, R>) => (_: Iterable<I>) => R} */
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} */
14
59
  const apply = ({ merge, init, result }) => pipe(reduce(merge)(init))(result)
15
60
 
16
- const sum = apply(mr.sum)
61
+ const sum = apply(seq.sum)
62
+
63
+ const size = apply(seq.size)
17
64
 
18
- const join = pipe(mr.join)(apply)
65
+ const join = pipe(seq.join)(apply)
19
66
 
20
67
  /** @type {<T, R>(f: (value: T) => R) => (c: Iterable<T>) => Iterable<R>} */
21
68
  const map = f => c => ({
@@ -26,6 +73,16 @@ const map = f => c => ({
26
73
  }
27
74
  })
28
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
+
29
86
  module.exports = {
30
87
  /** @readonly */
31
88
  apply,
@@ -39,19 +96,21 @@ module.exports = {
39
96
  /** @readonly */
40
97
  sum,
41
98
 
99
+ /** @readonly */
100
+ size,
101
+
102
+ /** @readonly */
103
+ entries,
104
+
42
105
  /** @readonly */
43
106
  map,
44
107
 
45
- /**
46
- * @readonly
47
- * @type {<T>(_: (_: T) => boolean) => (_: Iterable<T>) => T|undefined}
48
- */
49
- find: f => c => {
50
- for (const i of c) {
51
- if (f(i)) {
52
- return i
53
- }
54
- }
55
- return undefined
56
- }
108
+ /** @readonly */
109
+ exclusiveScan,
110
+
111
+ /** @readonly */
112
+ inclusiveScan,
113
+
114
+ /** @readonly */
115
+ find,
57
116
  }
package/iterable/test.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const i = require('.')
2
- const { pipe } = require('../func')
2
+ const { pipe } = require('../function')
3
3
 
4
4
  {
5
5
  const r = i.sum([120, 300, 42])
@@ -38,4 +38,14 @@ const { pipe } = require('../func')
38
38
  (i.find(x => x !== undefined))
39
39
  ([() => p, () => `${p}.js`, () => `${p}/index.js`])
40
40
  if (x('index.js') !== 'x') { throw 'error' }
41
+ }
42
+
43
+ {
44
+ const x = JSON.stringify(Array.from(i.entries(['a', 'b', 'c'])))
45
+ if (x !== '[[0,"a"],[1,"b"],[2,"c"]]') { throw x }
46
+ }
47
+
48
+ {
49
+ const x = JSON.stringify(Array.from(i.entries([])))
50
+ if (x !== '[]') { throw x }
41
51
  }
@@ -1,9 +1,8 @@
1
1
  const array = require('../array')
2
- const { pipe } = require('../func')
2
+ const { pipe } = require('../function')
3
3
  const option = require('../option')
4
4
  const { head, last, splitLast, splitFirst } = array
5
5
  const iter = require('../iterable')
6
- const mr = require('../map-reduce')
7
6
 
8
7
  /**
9
8
  * @template T
@@ -39,7 +38,7 @@ const mr = require('../map-reduce')
39
38
 
40
39
  /** @typedef {(_: string) => undefined|Package|Dependencies} Dependencies */
41
40
 
42
- /** @type {mr.Operation<string, undefined|Path, undefined|Path>} */
41
+ /** @type {import('../sequence').Operation<string, undefined|Path, undefined|Path>} */
43
42
  const pathNormReduce = {
44
43
  merge: path => item =>
45
44
  path === undefined ?
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.163",
3
+ "version": "0.0.168",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -0,0 +1,131 @@
1
+ const { todo } = require('../dev')
2
+ const { id } = require('../function')
3
+
4
+ /**
5
+ * @template T0
6
+ * @template T1
7
+ * @typedef {import('../array').Tuple2<T0, T1>} Tuple2
8
+ */
9
+
10
+ /**
11
+ * @template T
12
+ * @template R
13
+ * @typedef {Tuple2<R, Scan<T, R>>} ScanResult
14
+ */
15
+
16
+ /**
17
+ * @template T
18
+ * @template R
19
+ * @typedef {(value: T) => ScanResult<T, R>} Scan
20
+ */
21
+
22
+ /**
23
+ * @template T
24
+ * @template R
25
+ * @typedef {{
26
+ * readonly scan: Scan<T, R>
27
+ * readonly first: R
28
+ * }} InclusiveScan
29
+ */
30
+
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 */
40
+ /** @typedef {RT[0]} R */
41
+ /** @typedef {RT[1]} T */
42
+ /** @type {(prior: R) => Scan<T, R>} */
43
+ const f = prior => value => {
44
+ const result = operator(prior)(value)
45
+ return [result, f(result)]
46
+ }
47
+ return f
48
+ }
49
+
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
+ })
55
+
56
+ /**
57
+ * @template T
58
+ * @typedef {Tuple2<number, T>} Entry
59
+ */
60
+
61
+ /** @type {(index: number) => <T>(value: T) => ScanResult<T, Entry<T>>} */
62
+ const createEntries = index => value => [[index, value], createEntries(index + 1)]
63
+
64
+ const entries = createEntries(0)
65
+
66
+ /** @type {(separator: string) => BinaryOperator<string, string>} */
67
+ const joinOperation = separator => prior => value => `${prior}${separator}${value}`
68
+
69
+ /** @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
77
+
78
+ /** @type {InclusiveScan<number, number>} */
79
+ const sum2 = inclusiveOperatorScan(addition)(0)
80
+
81
+ ////
82
+
83
+ /**
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
92
+ */
93
+
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
+ }
107
+
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
+ }
120
+
121
+ module.exports = {
122
+ /** @readonly */
123
+ join,
124
+ join2,
125
+ /** @readonly */
126
+ sum,
127
+ /** @readonly */
128
+ size,
129
+ /** @readonly */
130
+ entries,
131
+ }
package/test.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const i = require('./')
2
2
 
3
+ require('./iterable/test')
3
4
  require('./async/iterable/test')
4
5
  require('./module-manager/test')
5
6
 
package/func/index.js DELETED
@@ -1,12 +0,0 @@
1
- /** @type {<I, X>(_: (_: I) => X) => <O>(_: (_: X) => O) => (_: I) => O} */
2
- const pipe = g => f => x => f(g(x))
3
-
4
- /** @type {<T>(value: T) => T} */
5
- const id = value => value
6
-
7
- module.exports = {
8
- /** @readonly */
9
- id,
10
- /** @readonly */
11
- pipe,
12
- }
@@ -1,48 +0,0 @@
1
- const { pipe, id } = require('../func')
2
-
3
- /**
4
- * @template S
5
- * @template I
6
- * @typedef {(state: S) => (value: I) => S} Merge
7
- */
8
-
9
- /**
10
- * @template I
11
- * @template S
12
- * @template O
13
- * @typedef {{
14
- * readonly merge: Merge<S, I>
15
- * readonly result: (state: S) => O
16
- * readonly init: S
17
- * }} Operation
18
- */
19
-
20
- /** @type {<I, T>(mapFn: (value: I) => T) => <S, O>(op: Operation<T, S, O>) => Operation<I, S, O>} */
21
- const map = mapFn => ({ merge, result, init}) => ({
22
- merge: pipe(merge)(pipe(mapFn)),
23
- result,
24
- init,
25
- })
26
-
27
- /** @type {(separator: string) => Operation<string, string|undefined, string>} */
28
- const join = separator => ({
29
- merge: s => i => s === undefined ? i : `${s}${separator}${i}`,
30
- init: undefined,
31
- result: s => s === undefined ? '' : s
32
- })
33
-
34
- /** @type {Operation<number, number, number>} */
35
- const sum = {
36
- merge: a => i => a + i,
37
- result: id,
38
- init: 0,
39
- }
40
-
41
- module.exports = {
42
- /** @readonly */
43
- map,
44
- /** @readonly */
45
- join,
46
- /** @readonly */
47
- sum,
48
- }