functionalscript 0.0.190 → 0.0.191

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
@@ -305,28 +305,25 @@ const replaceVisitor = {
305
305
  notFound: notFoundGet,
306
306
  }
307
307
 
308
- /** @type {<T>(...array: readonly seq.Sequence<T>[]) => seq.Sequence<T>} */
309
- const flatArray = (...array) => seq.flat(seq.fromArray(array))
310
-
311
308
  /** @type {<T>(node: Node<T>) => seq.Sequence<T>} */
312
- const valuesList = node => () => {
309
+ const values = node => () => {
313
310
  const f = () => {
314
311
  switch (node.length) {
315
- case 1: case 2: { return seq.fromArray(node) }
312
+ case 1: case 2: { return seq.list(...node) }
316
313
  case 3: {
317
- return flatArray(
318
- valuesList(node[0]),
319
- seq.one(node[1]),
320
- valuesList(node[2])
314
+ return seq.concat(
315
+ values(node[0]),
316
+ seq.list(node[1]),
317
+ values(node[2])
321
318
  )
322
319
  }
323
320
  default: {
324
- return flatArray(
325
- valuesList(node[0]),
326
- seq.one(node[1]),
327
- valuesList(node[2]),
328
- seq.one(node[3]),
329
- valuesList(node[4])
321
+ return seq.concat(
322
+ values(node[0]),
323
+ seq.list(node[1]),
324
+ values(node[2]),
325
+ seq.list(node[3]),
326
+ values(node[4])
330
327
  )
331
328
  }
332
329
  }
@@ -336,7 +333,7 @@ const valuesList = node => () => {
336
333
 
337
334
  module.exports = {
338
335
  /** @readonly */
339
- valuesList,
336
+ values,
340
337
  /**
341
338
  * @readonly
342
339
  * @type { <T>(cmp: Cmp<T>) => (node: Node<T>) => T|undefined }
package/btree/test.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const btree = require('.')
2
- const { setVisitor, valuesList } = btree
2
+ const { setVisitor, values: valuesList } = btree
3
3
  const { cmp } = require('../cmp')
4
4
  const list = require('../sequence')
5
5
 
package/json/index.js CHANGED
@@ -26,10 +26,10 @@ const addProperty = value => {
26
26
  }
27
27
 
28
28
  /** @type {(kv: readonly[string, seq.Sequence<string>]) => seq.Sequence<string>} */
29
- const property = ([k, v]) => seq.concat(seq.one(JSON.stringify(k)), seq.one(':'), v)
29
+ const property = ([k, v]) => seq.concat(seq.list(JSON.stringify(k)), seq.list(':'), v)
30
30
 
31
31
  /** @type {op.Scan<seq.Sequence<string>, seq.Sequence<string>>} */
32
- const commaValue = a => [seq.concat(seq.one(','), a), commaValue]
32
+ const commaValue = a => [seq.concat(seq.list(','), a), commaValue]
33
33
 
34
34
  /** @type {op.Scan<seq.Sequence<string>, seq.Sequence<string>>} */
35
35
  const joinScan = value => [value, commaValue]
@@ -39,8 +39,8 @@ const join = input => seq.flat(seq.scan(joinScan)(input))
39
39
 
40
40
  /** @type {(open: string) => (close: string) => (input: seq.Sequence<seq.Sequence<string>>) => seq.Sequence<string>} */
41
41
  const list = open => close => {
42
- const seqOpen = seq.one(open)
43
- const seqClose = seq.one(close)
42
+ const seqOpen = seq.list(open)
43
+ const seqClose = seq.list(close)
44
44
  return input => seq.concat(seqOpen, join(input), seqClose)
45
45
  }
46
46
 
@@ -51,10 +51,7 @@ const arrayList = list('[')(']')
51
51
  /** @type {(object: Object) => seq.Sequence<string>} */
52
52
  const objectStringify = object => {
53
53
  /** @type {map.Map<seq.Sequence<string>>} */
54
- let m = map.empty
55
- for (const [k, v] of Object.entries(object)) {
56
- m = m.set(k)(stringSeq(v))
57
- }
54
+ const m = seq.fold(m => ([k, v]) => m.set(k)(stringSeq(v)))(map.empty)(seq.fromArray(Object.entries(object)))
58
55
  return objectList(seq.map(property)(m.entries))
59
56
  }
60
57
 
@@ -65,12 +62,12 @@ const arrayStringify = array => arrayList(seq.map(stringSeq)(seq.fromArray(array
65
62
  const stringSeq = value => {
66
63
  const x = typeof value
67
64
  switch (typeof value) {
68
- case 'boolean': { return seq.one(value ? "true" : "false") }
65
+ case 'boolean': { return seq.list(value ? "true" : "false") }
69
66
  // Note: we shouldn't use JSON.stringify since it has non determenistic behavior.
70
67
  // In particular: property order could be different.
71
- case 'number': case 'string': { return seq.one(JSON.stringify(value)) }
68
+ case 'number': case 'string': { return seq.list(JSON.stringify(value)) }
72
69
  default: {
73
- if (value === null) { return seq.one("null") }
70
+ if (value === null) { return seq.list("null") }
74
71
  if (value instanceof Array) { return arrayStringify(value) }
75
72
  return objectStringify(value)
76
73
  }
package/map/index.js CHANGED
@@ -1,7 +1,8 @@
1
1
  const option = require("../option")
2
- const { getVisitor, setVisitor, valuesList } = require("../btree")
2
+ const { getVisitor, setVisitor, values: valuesList } = require("../btree")
3
3
  const { cmp } = require("../cmp")
4
- const list = require("../sequence")
4
+ const seq = require("../sequence")
5
+ const op = require("../sequence/operator")
5
6
 
6
7
  /** @typedef {import("../cmp").Sign} Sign */
7
8
 
@@ -30,7 +31,7 @@ const list = require("../sequence")
30
31
  * @typedef {{
31
32
  * readonly get: (name: string) => T|undefined
32
33
  * readonly set: (name: string) => (value: T) => Map<T>
33
- * readonly entries: list.Sequence<Entry<T>>
34
+ * readonly entries: seq.Sequence<Entry<T>>
34
35
  * readonly root: undefined|TNode<Entry<T>>
35
36
  * }} Map
36
37
  */
@@ -62,11 +63,16 @@ const create = root => ({
62
63
  const empty = {
63
64
  get: () => undefined,
64
65
  set: name => value => create([[name, value]]),
65
- entries: list.empty,
66
+ entries: seq.empty,
66
67
  root: undefined
67
68
  }
68
69
 
70
+ /** @type {<T>(entries: seq.Sequence<Entry<T>>) => Map<T>} */
71
+ const fromEntries = seq.fold(map => entry => map.set(entry))(empty)
72
+
69
73
  module.exports = {
70
74
  /** @readonly */
71
75
  empty,
76
+ /** @readonly */
77
+ fromEntries,
72
78
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.190",
3
+ "version": "0.0.191",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/sequence/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const array = require('./array')
2
2
  const seqOp = require('./operator')
3
3
  const { pipe } = require('../function')
4
+ const op = require('../function/operator')
4
5
  const { logicalNot, strictEqual } = require('../function/operator')
5
6
 
6
7
  /**
@@ -77,8 +78,20 @@ const first = input => {
77
78
  * @typedef {(list: Sequence<T>) => R} SequenceReduce
78
79
  */
79
80
 
80
- /** @type {<T>(first: T) => Sequence<T>} */
81
- const one = first => () => [first, empty]
81
+ /** @type {<T>(...array: readonly T[]) => Sequence<T>} */
82
+ const list = (...array) => {
83
+ /** @typedef {typeof array extends readonly(infer T)[] ? T : never} T */
84
+ let i = array.length
85
+ /** @type {Sequence<T>} */
86
+ let tail = empty
87
+ while (true) {
88
+ if (i === 0) { return tail }
89
+ i = i - 1
90
+ /** @type {FirstAndTail<T>} */
91
+ const result = [array[i], tail]
92
+ tail = () => result
93
+ }
94
+ }
82
95
 
83
96
  /** @type {<T>(array: array.Array<T>) => Sequence<T>} */
84
97
  const fromArray = a => {
@@ -92,11 +105,28 @@ const fromArray = a => {
92
105
  return at(0)
93
106
  }
94
107
 
95
- /** @type {<T>(a: Sequence<T>) => SequenceMap<T, T>} */
96
- const concat2 = a => b => [a, b]
97
-
98
108
  /** @type {<T>(...array: readonly Sequence<T>[]) => Sequence<T>} */
99
- const concat = (...a) => flat(fromArray(a))
109
+ const concat = (...array) => {
110
+ let i = array.length
111
+ if (i == 0) { return empty }
112
+ i = i - 1
113
+ let tail = array[i]
114
+ while (true) {
115
+ if (i === 0) { return tail }
116
+ i = i - 1
117
+ tail = [array[i], tail]
118
+ }
119
+ }
120
+
121
+ /** @type {(_: number) => Sequence<number>} */
122
+ const generate = n => {
123
+ /** @type {(_: number) => Sequence<number>} */
124
+ const f = i => () => {
125
+ if (n <= i) { return undefined }
126
+ return [i, f(i + 1)]
127
+ }
128
+ return f(0)
129
+ }
100
130
 
101
131
  /** @type {<T, R>(f: (value: T) => Sequence<R>) => SequenceMap<T, R>} */
102
132
  const flatMap = f => input => () => {
@@ -117,16 +147,16 @@ const flatMap = f => input => () => {
117
147
  const flat = flatMap(i => i)
118
148
 
119
149
  /** @type {<T, R>(f: (value: T) => R) => SequenceMap<T, R>} */
120
- const map = f => flatMap(i => one(f(i)))
150
+ const map = f => flatMap(i => list(f(i)))
121
151
 
122
152
  /** @type {<T>(f: (value: T) => boolean) => SequenceMap<T, T>} */
123
- const filter = f => flatMap(i => f(i) ? one(i) : empty)
153
+ const filter = f => flatMap(i => f(i) ? list(i) : empty)
124
154
 
125
155
  /** @type {<T, R>(f: (value: T) => R|undefined) => (value: T) => Sequence<R>} */
126
156
  const filterMapFunc = f => i => {
127
157
  const result = f(i)
128
158
  if (result === undefined) { return empty }
129
- return one(result)
159
+ return list(result)
130
160
  }
131
161
 
132
162
  /** @type {<T, R>(f: (value: T) => R|undefined) => SequenceMap<T, R>} */
@@ -163,6 +193,9 @@ const last = def => input => {
163
193
  /** @type {<T, R>(s: seqOp.ExclusiveScan<T, R>) => (input: Sequence<T>) => R} */
164
194
  const reduce = ([first, s]) => input => last(first)(scan(s)(input))
165
195
 
196
+ /** @type {<T, R>(ro: op.ReduceOperator<R, T>) => (first: R) => (input: Sequence<T>) => R} */
197
+ const fold = ro => first => reduce(seqOp.exclusiveScan(ro)(first))
198
+
166
199
  const entries = scan(seqOp.entries)
167
200
 
168
201
  const sum = reduce(seqOp.sum)
@@ -247,7 +280,7 @@ module.exports = {
247
280
  /** @readonly */
248
281
  next,
249
282
  /** @readonly */
250
- one,
283
+ list,
251
284
  /** @readonly */
252
285
  empty,
253
286
  /** @readonly */
@@ -255,7 +288,7 @@ module.exports = {
255
288
  /** @readonly */
256
289
  concat,
257
290
  /** @readonly */
258
- concat2,
291
+ generate,
259
292
  /** @readonly */
260
293
  first,
261
294
  /** @readonly */
@@ -283,6 +316,8 @@ module.exports = {
283
316
  /** @readonly */
284
317
  last,
285
318
  /** @readonly */
319
+ fold,
320
+ /** @readonly */
286
321
  reduce,
287
322
  /** @readonly */
288
323
  entries,
package/sequence/test.js CHANGED
@@ -8,7 +8,7 @@ const print = input => {
8
8
  while (true) {
9
9
  const result = seq.next(i)
10
10
  if (result === undefined) { return }
11
- // console.log(result[0])
11
+ console.log(result[0])
12
12
  i = result[1]
13
13
  }
14
14
  }
@@ -25,11 +25,23 @@ const print = input => {
25
25
  if (seq.some(x => x > 100)(big) !== false) { throw 'x' }
26
26
  if (seq.some(x => x > 50)(big) !== true) { throw 'x' }
27
27
  if (seq.first(seq.drop(16)(big)) !== 42) { throw 'drop'}
28
+ {
29
+ const a = seq.toArray(seq.generate(1_000_000))
30
+ let x = seq.concat(seq.fromArray(a), big)
31
+ const r = seq.next(x)
32
+ // print(x)
33
+ }
34
+ {
35
+ const a = seq.map(seq.generate)(seq.generate(100_000))
36
+ const array = seq.toArray(a)
37
+ const x = seq.concat(...array)
38
+ const r = seq.next(x)
39
+ // print(x)
40
+ }
28
41
  {
29
42
  let x = big
30
43
  for (let i = 0; i < 1_000_000; ++i) {
31
- // concat() still causes a stack overflow
32
- x = seq.concat2(seq.empty)(x)
44
+ x = seq.concat(seq.empty, x)
33
45
  }
34
46
  const r = seq.next(x)
35
47
  // print(x)
@@ -37,8 +49,7 @@ const print = input => {
37
49
  {
38
50
  let x = big
39
51
  for (let i = 0; i < 1_000_000; ++i) {
40
- // concat() still causes a stack overflow
41
- x = seq.concat2(x)(seq.one(i))
52
+ x = seq.concat(x, seq.list(i))
42
53
  }
43
54
  const r = seq.next(x)
44
55
  // print(x)