functionalscript 0.0.161 → 0.0.166

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
  /**
@@ -0,0 +1,121 @@
1
+ const { pipe } = require('../../func')
2
+ const mr = require('../../map-reduce')
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>} AnyIterator
18
+ */
19
+
20
+ /** @type {<T, R>(f: (value: T) => PromiseOrValue<R>) => (c: AnyIterator<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: AnyIterator<AnyIterator<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: AnyIterator<T>) => AnyIterator<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) => AnyIterator<R>) => (c: AnyIterator<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: AnyIterator<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: AnyIterator<T>) => (b: AnyIterator<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: AnyIterator<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 {<A, T>(merge: Merge<A, T>) => (init: A) => (c: AnyIterator<T>) => AsyncIterable<A>} */
87
+ const inclusiveScan = merge => init => c => concat([init])(exclusiveScan(merge)(init)(c))
88
+
89
+ /** @type {<I, S, R>(op: mr.Operation<I, S, R>) => (_: AnyIterator<I>) => Promise<R>} */
90
+ const apply = ({ merge, init, result }) => async c => result(await reduce(merge)(init)(c))
91
+
92
+ const sum = apply(mr.sum)
93
+
94
+ const join = pipe(mr.join)(apply)
95
+
96
+ const size = apply(mr.size)
97
+
98
+ module.exports = {
99
+ /** @readonly */
100
+ apply,
101
+ /** @readonly */
102
+ concat,
103
+ /** @readonly */
104
+ map,
105
+ /** @readonly */
106
+ filter,
107
+ /** @readonly */
108
+ flatMap,
109
+ /** @readonly */
110
+ reduce,
111
+ /** @readonly */
112
+ sum,
113
+ /** @readonly */
114
+ size,
115
+ /** @readonly */
116
+ join,
117
+ /** @readonly */
118
+ exclusiveScan,
119
+ /** @readonly */
120
+ inclusiveScan,
121
+ }
@@ -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
  }
package/func/index.js CHANGED
@@ -1,12 +1,40 @@
1
- /** @type {<I, X>(_: (_: I) => X) => <O>(_: (_: X) => O) => (_: I) => O} */
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>} */
2
11
  const pipe = g => f => x => f(g(x))
3
12
 
4
13
  /** @type {<T>(value: T) => T} */
5
14
  const id = value => value
6
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
+
7
31
  module.exports = {
8
32
  /** @readonly */
9
33
  id,
10
34
  /** @readonly */
11
35
  pipe,
36
+ /** @readonly */
37
+ combine,
38
+ /** @readonly */
39
+ pipex,
12
40
  }
package/iterable/index.js CHANGED
@@ -1,7 +1,13 @@
1
1
  const { pipe } = require('../func')
2
2
  const mr = require('../map-reduce')
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,8 +16,69 @@ const reduce = merge => init => c => {
10
16
  return result
11
17
  }
12
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: mr.ExlusiveScan<T, R>) => (c: Iterable<T>) => Iterable<R>} */
42
+ const applyExclusiveScan = 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
+ const entries = applyExclusiveScan(mr.entries)
54
+
13
55
  /** @type {<I, S, R>(op: mr.Operation<I, S, R>) => (_: Iterable<I>) => R} */
14
- const apply = op => pipe(reduce(op.reduce)(op.init))(op.result)
56
+ const apply = ({ merge, init, result }) => pipe(reduce(merge)(init))(result)
57
+
58
+ const sum = apply(mr.sum)
59
+
60
+ const size = apply(mr.size)
61
+
62
+ const join = pipe(mr.join)(apply)
63
+
64
+ /** @type {<T, R>(f: (value: T) => R) => (c: Iterable<T>) => Iterable<R>} */
65
+ const map = f => c => ({
66
+ *[Symbol.iterator]() {
67
+ for (const i of c) {
68
+ yield f(i)
69
+ }
70
+ }
71
+ })
72
+
73
+ /** @type {<T>(_: (_: T) => boolean) => (_: Iterable<T>) => T|undefined} */
74
+ const find = f => c => {
75
+ for (const i of c) {
76
+ if (f(i)) {
77
+ return i
78
+ }
79
+ }
80
+ return undefined
81
+ }
15
82
 
16
83
  module.exports = {
17
84
  /** @readonly */
@@ -21,33 +88,26 @@ module.exports = {
21
88
  reduce,
22
89
 
23
90
  /** @readonly */
24
- join: pipe(mr.join)(apply),
91
+ join,
25
92
 
26
93
  /** @readonly */
27
- sum: apply(mr.sum),
94
+ sum,
28
95
 
29
- /**
30
- * @readonly
31
- * @type {<T, R>(f: (value: T) => R) => (c: Iterable<T>) => Iterable<R>}
32
- */
33
- map: f => c => ({
34
- *[Symbol.iterator]() {
35
- for (const i of c) {
36
- yield f(i)
37
- }
38
- }
39
- }),
96
+ /** @readonly */
97
+ size,
40
98
 
41
- /**
42
- * @readonly
43
- * @type {<T>(_: (_: T) => boolean) => (_: Iterable<T>) => T|undefined}
44
- */
45
- find: f => c => {
46
- for (const i of c) {
47
- if (f(i)) {
48
- return i
49
- }
50
- }
51
- return undefined
52
- }
99
+ /** @readonly */
100
+ entries,
101
+
102
+ /** @readonly */
103
+ map,
104
+
105
+ /** @readonly */
106
+ exclusiveScan,
107
+
108
+ /** @readonly */
109
+ inclusiveScan,
110
+
111
+ /** @readonly */
112
+ find,
53
113
  }
package/iterable/test.js CHANGED
@@ -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,37 +1,72 @@
1
1
  const { pipe, id } = require('../func')
2
2
 
3
+ /**
4
+ * @template S
5
+ * @template I
6
+ * @typedef {(state: S) => (value: I) => S} Merge
7
+ */
8
+
3
9
  /**
4
10
  * @template I
5
11
  * @template S
6
12
  * @template O
7
13
  * @typedef {{
8
- * readonly reduce: (state: S) => (value: I) => S
14
+ * readonly merge: Merge<S, I>
9
15
  * readonly result: (state: S) => O
10
16
  * readonly init: S
11
17
  * }} Operation
12
18
  */
13
19
 
14
20
  /** @type {<I, T>(mapFn: (value: I) => T) => <S, O>(op: Operation<T, S, O>) => Operation<I, S, O>} */
15
- const map = mapFn => ({ reduce, result, init}) => ({
16
- reduce: pipe(reduce)(pipe(mapFn)),
21
+ const map = mapFn => ({ merge, result, init}) => ({
22
+ merge: pipe(merge)(pipe(mapFn)),
17
23
  result,
18
24
  init,
19
25
  })
20
26
 
21
27
  /** @type {(separator: string) => Operation<string, string|undefined, string>} */
22
28
  const join = separator => ({
23
- reduce: s => i => s === undefined ? i : `${s}${separator}${i}`,
29
+ merge: s => i => s === undefined ? i : `${s}${separator}${i}`,
24
30
  init: undefined,
25
31
  result: s => s === undefined ? '' : s
26
32
  })
27
33
 
28
34
  /** @type {Operation<number, number, number>} */
29
35
  const sum = {
30
- reduce: a => i => a + i,
36
+ merge: a => i => a + i,
31
37
  result: id,
32
38
  init: 0,
33
39
  }
34
40
 
41
+ /**
42
+ * @type {{
43
+ * readonly merge: (counter: number) => () => number
44
+ * readonly result: (counter: number) => number
45
+ * readonly init: number
46
+ * }}
47
+ */
48
+ const size = {
49
+ merge: counter => () => counter + 1,
50
+ init: 0,
51
+ result: id,
52
+ }
53
+
54
+ /**
55
+ * @template T
56
+ * @template R
57
+ * @typedef {(value: T) => readonly [R, ExlusiveScan<T, R>]} ExlusiveScan
58
+ */
59
+
60
+ /**
61
+ * @template T
62
+ * @typedef {readonly[number, T]} Entry
63
+ */
64
+
65
+ /** @type {(index: number) => <T>(value: T) => readonly[Entry<T>, ExlusiveScan<T, Entry<T>>]} */
66
+ const entriesFrom = index => value => [[index, value], entriesFrom(index + 1)]
67
+
68
+ const entries = entriesFrom(0)
69
+
35
70
  module.exports = {
36
71
  /** @readonly */
37
72
  map,
@@ -39,4 +74,8 @@ module.exports = {
39
74
  join,
40
75
  /** @readonly */
41
76
  sum,
77
+ /** @readonly */
78
+ size,
79
+ /** @readonly */
80
+ entries,
42
81
  }
@@ -3,7 +3,6 @@ const { pipe } = require('../func')
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,9 +38,9 @@ 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('../map-reduce').Operation<string, undefined|Path, undefined|Path>} */
43
42
  const pathNormReduce = {
44
- reduce: path => item =>
43
+ merge: path => item =>
45
44
  path === undefined ?
46
45
  undefined :
47
46
  ['', '.'].includes(item) ?
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.161",
3
+ "version": "0.0.166",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/test.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const i = require('./')
2
2
 
3
- require('./async/test')
3
+ require('./iterable/test')
4
+ require('./async/iterable/test')
4
5
  require('./module-manager/test')
5
6
 
6
7
  /** @type {() => never} */
package/async/index.js DELETED
@@ -1,101 +0,0 @@
1
- const { pipe } = require('../func')
2
-
3
- /** @type {<T, R>(f: (value: T) => Promise<R>) => (c: AsyncIterable<T>) => AsyncIterable<R>} */
4
- const map = f => c => ({
5
- async *[Symbol.asyncIterator]() {
6
- for await (const i of c) {
7
- yield f(i)
8
- }
9
- }
10
- })
11
-
12
- /** @type {<T>(c: AsyncIterable<AsyncIterable<T>>) => AsyncIterable<T>} */
13
- const flatten = c => ({
14
- async *[Symbol.asyncIterator]() {
15
- for await (const i of c) {
16
- yield *i
17
- }
18
- }
19
- })
20
-
21
- /** @type {<T>(f: (value: T) => Promise<boolean>) => (c: AsyncIterable<T>) => AsyncIterable<T>} */
22
- const filter = f => c => ({
23
- async *[Symbol.asyncIterator]() {
24
- for await (const i of c) {
25
- if (await f(i)) {
26
- yield i
27
- }
28
- }
29
- }
30
- })
31
-
32
- /** @type {<T, R>(f: (value: T) => AsyncIterable<R>) => (c: AsyncIterable<T>) => AsyncIterable<R>} */
33
- const flatMap = f => pipe(map(async x => f(x)))(flatten)
34
-
35
- /**
36
- * @template A
37
- * @template T
38
- * @typedef {(accumulator: A) => (value: T) => Promise<A>} ReduceFn
39
- */
40
-
41
- /** @type {<A, T>(f: ReduceFn<A, T>) => (init: A) => (c: AsyncIterable<T>) => Promise<A>} */
42
- const reduce = reduceFn => init => async c => {
43
- let result = init
44
- for await (const i of c) {
45
- result = await reduceFn(result)(i)
46
- }
47
- return result
48
- }
49
-
50
- /** @type {<A, T>(f: ReduceFn<A, T>) => (init: A) => (c: AsyncIterable<T>) => AsyncIterable<A>} */
51
- const exclusiveScan = reduceFn => init => c => ({
52
- async *[Symbol.asyncIterator]() {
53
- let result = init
54
- for await (const i of c) {
55
- result = await reduceFn(result)(i)
56
- yield result
57
- }
58
- }
59
- })
60
-
61
- /** @type {<A, T>(f: ReduceFn<A, T>) => (init: A) => (c: AsyncIterable<T>) => AsyncIterable<A>} */
62
- const inclusiveScan = reduceFn => init => {
63
- const e = exclusiveScan(reduceFn)(init)
64
- return c => ({
65
- async *[Symbol.asyncIterator]() {
66
- yield init
67
- yield *e(c)
68
- }
69
- })
70
- }
71
-
72
- /** @type {<T>(iterable: Iterable<T>) => AsyncIterable<T>} */
73
- const cast = iterable => ({
74
- async *[Symbol.asyncIterator]() {
75
- for (const i of iterable) {
76
- yield i
77
- }
78
- }
79
- })
80
-
81
- /** @type {(c: AsyncIterable<number>) => Promise<number>} */
82
- const sum = reduce(a => async v => a + v)(0)
83
-
84
- module.exports = {
85
- /** @readonly */
86
- cast,
87
- /** @readonly */
88
- map,
89
- /** @readonly */
90
- filter,
91
- /** @readonly */
92
- flatMap,
93
- /** @readonly */
94
- reduce,
95
- /** @readonly */
96
- sum,
97
- /** @readonly */
98
- exclusiveScan,
99
- /** @readonly */
100
- inclusiveScan,
101
- }