functionalscript 0.0.182 → 0.0.185

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.
@@ -1,18 +1,41 @@
1
+ /**
2
+ * @template A
3
+ * @template B
4
+ * @template R
5
+ * @typedef {(a: A) => (b: B) => R} BinaryOperator
6
+ */
7
+
1
8
  /**
2
9
  * @template R
3
10
  * @template T
4
- * @typedef {(prior: R) => (value: T) => R} BinaryOperator
11
+ * @typedef {BinaryOperator<R, T, R>} ReduceOperator
5
12
  */
6
13
 
7
- /** @type {(separator: string) => BinaryOperator<string, string>} */
14
+ /** @type {(separator: string) => ReduceOperator<string, string>} */
8
15
  const join = separator => prior => value => `${prior}${separator}${value}`
9
16
 
10
17
  /** @type {(sum: number) => (value: number) => number} */
11
18
  const addition = a => b => a + b
12
19
 
20
+ /**
21
+ * @template T
22
+ * @template R
23
+ * @typedef {(value: T) => R} UnaryOperator
24
+ */
25
+
26
+ /** @type {(value: boolean) => boolean} */
27
+ const logicalNot = v => !v
28
+
29
+ /** @type {<T>(a: T) => (b: T) => boolean} */
30
+ const strictEqual = a => b => a === b
31
+
13
32
  module.exports = {
14
33
  /** @readonly */
15
34
  join,
16
35
  /** @readonly */
17
36
  addition,
37
+ /** @readonly */
38
+ strictEqual,
39
+ /** @readonly */
40
+ logicalNot,
18
41
  }
package/map/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const option = require("../option")
2
- const { getVisitor, setVisitor, values } = require("../btree")
2
+ const { getVisitor, setVisitor, valuesList } = require("../btree")
3
3
  const { cmp } = require("../cmp")
4
+ const list = require("../sequence/list")
4
5
 
5
6
  /** @typedef {import("../cmp").Sign} Sign */
6
7
 
@@ -29,7 +30,7 @@ const { cmp } = require("../cmp")
29
30
  * @typedef {{
30
31
  * readonly get: (name: string) => T|undefined
31
32
  * readonly set: (name: string) => (value: T) => Map<T>
32
- * readonly entries: () => Iterable<Entry<T>>
33
+ * readonly entries: list.List<Entry<T>>
33
34
  * readonly root: undefined|TNode<Entry<T>>
34
35
  * }} Map
35
36
  */
@@ -46,7 +47,7 @@ const create = root => ({
46
47
  if ('overflow' in result) { return create(result.overflow) }
47
48
  throw ''
48
49
  },
49
- entries: () => values(root),
50
+ entries: valuesList(root),
50
51
  root,
51
52
  })
52
53
 
@@ -54,14 +55,14 @@ const create = root => ({
54
55
  * @type {{
55
56
  * readonly get: (name: string) => undefined
56
57
  * readonly set: (name: string) => <T>(value: T) => Map<T>
57
- * readonly entries: () => readonly []
58
+ * readonly entries: () => undefined
58
59
  * readonly root: undefined
59
60
  * }}
60
61
  */
61
62
  const empty = {
62
63
  get: () => undefined,
63
64
  set: name => value => create([[name, value]]),
64
- entries: () => [],
65
+ entries: list.empty,
65
66
  root: undefined
66
67
  }
67
68
 
package/map/test.js CHANGED
@@ -1,4 +1,5 @@
1
1
  const { empty } = require('.')
2
+ const list = require('../sequence/list')
2
3
 
3
4
  {
4
5
  let m = empty.set('a')(1)
@@ -44,7 +45,7 @@ const { empty } = require('.')
44
45
  if (m.get('x') !== 12) { throw 'error' }
45
46
  if (m.get('y') !== 44) { throw 'error' }
46
47
  if (m.get('a') !== undefined) { throw 'error' }
47
- const entries = Array.from(m.entries())
48
+ const entries = Array.from(list.iterable(m.entries))
48
49
  if (entries.length !== 2) { throw 'error' }
49
50
  }
50
51
 
@@ -39,8 +39,8 @@ const seq = require('../sequence')
39
39
 
40
40
  /** @typedef {(_: string) => undefined|Package|Dependencies} Dependencies */
41
41
 
42
- /** @type {seq.InclusiveScan<string, undefined|Path>} */
43
- const pathNormReduce = seq.inclusiveScan
42
+ /** @type {seq.ExclusiveScan<string, undefined|Path>} */
43
+ const pathNormReduce = seq.exclusiveScan
44
44
  (path => item =>
45
45
  path === undefined ?
46
46
  undefined :
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.182",
3
+ "version": "0.0.185",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -55,10 +55,10 @@ const scan = s => c => ({
55
55
  }
56
56
  })
57
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))
58
+ /** @type {<T, R>(s: seq.ExclusiveScan<T, R>) => (c: AsyncOrSyncIterable<T>) => AsyncIterable<R>} */
59
+ const exclusiveScan = ([first, s]) => c => concat([first])(scan(s)(c))
60
60
 
61
- /** @type {<T, R>(is: seq.InclusiveScan<T, R>) => (c: AsyncOrSyncIterable<T>) => Promise<R>} */
61
+ /** @type {<T, R>(is: seq.ExclusiveScan<T, R>) => (c: AsyncOrSyncIterable<T>) => Promise<R>} */
62
62
  const reduce = ([first, s]) => async c => {
63
63
  let next = first
64
64
  for await (const i of scan(s)(c)) {
@@ -105,7 +105,7 @@ module.exports = {
105
105
  /** @readonly */
106
106
  scan,
107
107
  /** @readonly */
108
- inclusiveScan,
108
+ exclusiveScan,
109
109
  /** @readonly */
110
110
  takeWhile,
111
111
  }
package/sequence/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  const op = require('../function/operator')
2
- const { id } = require('../function')
3
2
 
4
3
  /**
5
4
  * @template T0
@@ -22,12 +21,12 @@ const { id } = require('../function')
22
21
  /**
23
22
  * @template T
24
23
  * @template R
25
- * @typedef {Tuple2<R, Scan<T, R>>} InclusiveScan
24
+ * @typedef {Tuple2<R, Scan<T, R>>} ExclusiveScan
26
25
  */
27
26
 
28
- /** @type {<R, T>(operator: op.BinaryOperator<R, T>) => (prior: R) => Scan<T, R>} */
27
+ /** @type {<R, T>(operator: op.ReduceOperator<R, T>) => (prior: R) => Scan<T, R>} */
29
28
  const scan = operator => {
30
- /** @typedef {typeof operator extends op.BinaryOperator<infer R, infer T> ? [R, T] : never} RT */
29
+ /** @typedef {typeof operator extends op.ReduceOperator<infer R, infer T> ? [R, T] : never} RT */
31
30
  /** @typedef {RT[0]} R */
32
31
  /** @typedef {RT[1]} T */
33
32
  /** @type {(prior: R) => Scan<T, R>} */
@@ -38,8 +37,8 @@ const scan = operator => {
38
37
  return f
39
38
  }
40
39
 
41
- /** @type {<R, T>(operator: op.BinaryOperator<R, T>) => (first: R) => InclusiveScan<T, R>} */
42
- const inclusiveScan = operator => first => [first, scan(operator)(first)]
40
+ /** @type {<R, T>(operator: op.ReduceOperator<R, T>) => (first: R) => ExclusiveScan<T, R>} */
41
+ const exclusiveScan = operator => first => [first, scan(operator)(first)]
43
42
 
44
43
  /**
45
44
  * @template T
@@ -51,15 +50,15 @@ const createEntries = index => value => [[index, value], createEntries(index + 1
51
50
 
52
51
  const entries = createEntries(0)
53
52
 
54
- /** @type {(separator: string) => InclusiveScan<string, string>} */
53
+ /** @type {(separator: string) => ExclusiveScan<string, string>} */
55
54
  const join = separator => ['', value => [value, scan(op.join(separator))(value)]]
56
55
 
57
- const sum = inclusiveScan(op.addition)(0)
56
+ const sum = exclusiveScan(op.addition)(0)
58
57
 
59
58
  /** @type {(a: number) => () => number} */
60
59
  const counter = a => () => a + 1
61
60
 
62
- const length = inclusiveScan(counter)(0)
61
+ const length = exclusiveScan(counter)(0)
63
62
 
64
63
  /**
65
64
  * @template T
@@ -75,7 +74,7 @@ const filter = flatMap => f => flatMap(x => f(x) ? [x] : [])
75
74
 
76
75
  module.exports = {
77
76
  /** @readonly */
78
- inclusiveScan,
77
+ exclusiveScan,
79
78
  /** @readonly */
80
79
  scan,
81
80
  /** @readonly */
@@ -21,10 +21,10 @@ const scan = s => c => ({
21
21
  }
22
22
  })
23
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))
24
+ /** @type {<T, R>(s: seq.ExclusiveScan<T, R>) => (c: Iterable<T>) => Iterable<R>} */
25
+ const exclusiveScan = ([first, s]) => c => concat([first])(scan(s)(c))
26
26
 
27
- /** @type {<T, R>(s: seq.InclusiveScan<T, R>) => (c: Iterable<T>) => R} */
27
+ /** @type {<T, R>(s: seq.ExclusiveScan<T, R>) => (c: Iterable<T>) => R} */
28
28
  const reduce = ([first, s]) => c => {
29
29
  let next = first
30
30
  for (const i of scan(s)(c)) {
@@ -93,7 +93,7 @@ module.exports = {
93
93
  /** @readonly */
94
94
  scan,
95
95
  /** @readonly */
96
- inclusiveScan,
96
+ exclusiveScan,
97
97
  /** @readonly */
98
98
  flatMap,
99
99
  /** @readonly */
@@ -1,8 +1,7 @@
1
1
  const array = require('../array')
2
- const option = require('../../option')
3
2
  const base = require('..')
4
3
  const { pipe } = require('../../function')
5
- const { todo } = require('../../dev')
4
+ const { logicalNot, strictEqual } = require('../../function/operator')
6
5
 
7
6
  /**
8
7
  * @template T
@@ -15,13 +14,12 @@ const { todo } = require('../../dev')
15
14
  */
16
15
 
17
16
  /**
17
+ * Use `next` function to get `first` and `tail` of the list.
18
+ *
18
19
  * Please note that the list also contains `Concat<T>. We need this as
19
20
  * a workaround because modern JavaScript implementations don't support
20
- * ES6 TCO (Tail Call Optimization).
21
- *
22
- * Without this wotkaround we may have a stack overflow if a list
23
- * contains a lot of concateneted lists. Use `next` function to extract
24
- * a list.
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.
25
23
  *
26
24
  * @template T
27
25
  * @typedef { ListFunc<T> | Concat<T>} List
@@ -60,12 +58,25 @@ const next = list => {
60
58
  }
61
59
  }
62
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
+
63
68
  /**
64
69
  * @template T
65
70
  * @template R
66
71
  * @typedef {(list: List<T>) => List<R>} ListMap
67
72
  */
68
73
 
74
+ /**
75
+ * @template T
76
+ * @template R
77
+ * @typedef {(list: List<T>) => R} ListReduce
78
+ */
79
+
69
80
  /** @type {<T>(first: T) => List<T>} */
70
81
  const one = first => () => [first, empty]
71
82
 
@@ -109,6 +120,16 @@ const map = f => flatMap(i => one(f(i)))
109
120
  /** @type {<T>(f: (value: T) => boolean) => ListMap<T, T>} */
110
121
  const filter = f => flatMap(i => f(i) ? one(i) : empty)
111
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
+
112
133
  /** @type {<T, R>(s: base.Scan<T, R>) => ListMap<T, R>} */
113
134
  const scan = s => input => () => {
114
135
  const result = next(input)
@@ -120,8 +141,8 @@ const scan = s => input => () => {
120
141
  return [newFirst, scan(newS)(tail)]
121
142
  }
122
143
 
123
- /** @type {<T, R>(s: base.InclusiveScan<T, R>) => ListMap<T, R>} */
124
- const inclusiveScan = ([first, s]) => input => () => [first, scan(s)(input)]
144
+ /** @type {<T, R>(s: base.ExclusiveScan<T, R>) => ListMap<T, R>} */
145
+ const exclusiveScan = ([first, s]) => input => () => [first, scan(s)(input)]
125
146
 
126
147
  /** @type {<T>(def: T) => (input: List<T>) => T} */
127
148
  const last = def => input => {
@@ -135,10 +156,9 @@ const last = def => input => {
135
156
  r = result[0]
136
157
  i = result[1]
137
158
  }
138
- return r
139
159
  }
140
160
 
141
- /** @type {<T, R>(s: base.InclusiveScan<T, R>) => (input: List<T>) => R} */
161
+ /** @type {<T, R>(s: base.ExclusiveScan<T, R>) => (input: List<T>) => R} */
142
162
  const reduce = ([first, s]) => input => last(first)(scan(s)(input))
143
163
 
144
164
  const entries = scan(base.entries)
@@ -156,17 +176,34 @@ const takeWhile = f => input => () => {
156
176
  return result
157
177
  }
158
178
 
159
- /** @type {<T>(f: (value: T) => boolean) => (input: List<T>) => T|undefined} */
160
- const find = f => input => {
161
- const result = next(filter(f)(input))
162
- if (result === undefined) { return undefined }
163
- return result[0]
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
+ }
164
189
  }
165
190
 
166
- /**
167
- * Note: probably, it's possible to implement using the `scan` concept.
168
- * @type {<T>(list: List<T>) => Iterable<T>}
169
- */
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>} */
170
207
  const iterable = list => ({
171
208
  *[Symbol.iterator]() {
172
209
  let i = list
@@ -179,6 +216,31 @@ const iterable = list => ({
179
216
  }
180
217
  })
181
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
+
182
244
  module.exports = {
183
245
  /** @readonly */
184
246
  next,
@@ -187,12 +249,20 @@ module.exports = {
187
249
  /** @readonly */
188
250
  empty,
189
251
  /** @readonly */
252
+ at,
253
+ /** @readonly */
190
254
  concat,
191
255
  /** @readonly */
256
+ first,
257
+ /** @readonly */
192
258
  fromArray,
193
259
  /** @readonly */
260
+ toArray,
261
+ /** @readonly */
194
262
  iterable,
195
263
  /** @readonly */
264
+ asyncIterable,
265
+ /** @readonly */
196
266
  flatMap,
197
267
  /** @readonly */
198
268
  flat,
@@ -201,9 +271,11 @@ module.exports = {
201
271
  /** @readonly */
202
272
  filter,
203
273
  /** @readonly */
274
+ filterMap,
275
+ /** @readonly */
204
276
  scan,
205
277
  /** @readonly */
206
- inclusiveScan,
278
+ exclusiveScan,
207
279
  /** @readonly */
208
280
  last,
209
281
  /** @readonly */
@@ -217,7 +289,17 @@ module.exports = {
217
289
  /** @readonly */
218
290
  length,
219
291
  /** @readonly */
292
+ drop,
293
+ /** @readonly */
220
294
  find,
221
295
  /** @readonly */
222
296
  takeWhile,
297
+ /** @readonly */
298
+ some,
299
+ /** @readonly */
300
+ every,
301
+ /** @readonly */
302
+ includes,
303
+ /** @readonly */
304
+ zip,
223
305
  }
@@ -7,7 +7,7 @@ const print = a => {
7
7
  while (true) {
8
8
  const result = list.next(i)
9
9
  if (result === undefined) { return }
10
- console.log(result[0])
10
+ // console.log(result[0])
11
11
  i = result[1]
12
12
  }
13
13
  }
@@ -17,15 +17,20 @@ const print = a => {
17
17
  const list0 = list.fromArray([0, 1, 2, 3])
18
18
  const list1 = list.flatMap(x => list.fromArray([x, x * 2, x * 3]))(list0)
19
19
  const list2 = list.concat(list0)(list0)
20
- const list3 = list.inclusiveScan(sum)(list0)
20
+ const list3 = list.exclusiveScan(sum)(list0)
21
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'}
22
27
  {
23
28
  let x = big
24
29
  for (let i = 0; i < 1_000_000; ++i) {
25
30
  x = list.concat(list.empty)(x)
26
31
  }
27
32
  const r = list.next(x)
28
- print(x)
33
+ // print(x)
29
34
  }
30
35
  {
31
36
  let x = big