functionalscript 0.0.191 → 0.0.200

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,5 @@
1
- const { index3, index5 } = require('../cmp')
1
+ const cmp = require('../cmp')
2
+ const { index3, index5 } = cmp
2
3
  const seq = require('../sequence')
3
4
 
4
5
  /**
@@ -8,29 +9,29 @@ const seq = require('../sequence')
8
9
 
9
10
  /**
10
11
  * @template T
11
- * @typedef {import('../cmp').Cmp<T>} Cmp
12
+ * @typedef {cmp.Cmp<T>} Cmp
12
13
  */
13
14
 
14
15
  /**
15
16
  * @template T
16
- * @typedef {import('../sequence/array').Array1<T>} Array1
17
+ * @typedef {readonly[T]} Array1
17
18
  */
18
19
 
19
20
  /**
20
21
  * @template T
21
- * @typedef {import('../sequence/array').Array2<T>} Array2
22
+ * @typedef {readonly[T,T]} Array2
22
23
  */
23
24
 
24
25
  /**
25
26
  * @template T
26
- * @typedef {import('../sequence/array').Array3<T>} Array3
27
+ * @typedef {readonly[T,T,T]} Array3
27
28
  */
28
29
 
29
- /** @typedef {import('../sequence/array').Index2} Index2 */
30
+ /** @typedef {0|1} Index2 */
30
31
 
31
- /** @typedef {import('../sequence/array').Index3} Index3 */
32
+ /** @typedef {0|1|2} Index3 */
32
33
 
33
- /** @typedef {import('../sequence/array').Index5} Index5 */
34
+ /** @typedef {0|1|2|3|4} Index5 */
34
35
 
35
36
  //
36
37
 
@@ -59,14 +60,11 @@ const seq = require('../sequence')
59
60
  * @typedef { Leaf1<T> | Leaf2<T> | Branch3<T> | Branch5<T>} Node
60
61
  */
61
62
 
62
- /** @typedef {{ readonly done: false }} NotFoundDone */
63
+ /** @typedef {readonly['done']} NotFoundDone */
63
64
 
64
65
  /**
65
66
  * @template T
66
- * @typedef {{
67
- * readonly done: true
68
- * readonly value: T
69
- * }} FoundDone
67
+ * @typedef {readonly['done', T]} FoundDone
70
68
  */
71
69
 
72
70
  /**
@@ -76,12 +74,12 @@ const seq = require('../sequence')
76
74
 
77
75
  /**
78
76
  * @template T
79
- * @typedef {{ readonly replace: Node<T> }} Replace
77
+ * @typedef {readonly['replace', Node<T>]} Replace
80
78
  */
81
79
 
82
80
  /**
83
81
  * @template T
84
- * @typedef {{ readonly overflow: Branch3<T> }} Overflow
82
+ * @typedef {readonly['overflow', Branch3<T>]} Overflow
85
83
  */
86
84
 
87
85
  /**
@@ -137,9 +135,11 @@ const split = ([n0, v1, n2, v3, n4, v5, n6]) => [[n0, v1, n2], v3, [n4, v5, n6]]
137
135
  * Result<T>}
138
136
  */
139
137
  const merge = overflow => replace => result => {
140
- if ('done' in result) { return result }
141
- if ('replace' in result) { return { replace: replace(result.replace) } }
142
- return overflow(result.overflow)
138
+ switch (result[0]) {
139
+ case 'done': { return result }
140
+ case 'replace': { return ['replace', replace(result[1])] }
141
+ default: { return overflow(result[1]) }
142
+ }
143
143
  }
144
144
 
145
145
  /**
@@ -148,7 +148,7 @@ const merge = overflow => replace => result => {
148
148
  * (result: Result<T>) =>
149
149
  * Result<T>}
150
150
  */
151
- const merge2 = overflow => merge(o => ({ replace: overflow(o) }))
151
+ const merge2 = overflow => merge(o => ['replace', overflow(o)])
152
152
 
153
153
  /**
154
154
  * @type {<T>(overflow: (o: Branch3<T>) => Branch7<T>) =>
@@ -156,7 +156,7 @@ const merge2 = overflow => merge(o => ({ replace: overflow(o) }))
156
156
  * (result: Result<T>) =>
157
157
  * Result<T>}
158
158
  */
159
- const merge3 = overflow => merge(o => ({ overflow: split(overflow(o)) }))
159
+ const merge3 = overflow => merge(o => ['overflow', split(overflow(o))])
160
160
 
161
161
  /** @type {(visitor: Visitor) => <T>(cmp: Cmp<T>) => (init: Lazy<T>) => (node: Node<T>) => Result<T>} */
162
162
  const visit = ({ found, notFound }) => cmp => {
@@ -233,7 +233,7 @@ const visit = ({ found, notFound }) => cmp => {
233
233
  }
234
234
 
235
235
  /** @type { <T>(_: T) => Done<T> } */
236
- const found = value => ({ done: true, value })
236
+ const found = value => ['done', value]
237
237
 
238
238
  /** @type {Found} */
239
239
  const foundGet = {
@@ -245,7 +245,7 @@ const foundGet = {
245
245
  branch5_right: () => ([, , , value]) => found(value),
246
246
  }
247
247
  /** @type { () => () => NotFoundDone } */
248
- const notFound = () => () => ({ done: false })
248
+ const notFound = () => () => ['done']
249
249
 
250
250
  /** @type {NotFound} */
251
251
  const notFoundGet = {
@@ -257,7 +257,7 @@ const notFoundGet = {
257
257
  }
258
258
 
259
259
  /** @type { <T>(_: Node<T>) => Replace<T> } */
260
- const replace = node => ({ replace: node })
260
+ const replace = node => ['replace', node]
261
261
 
262
262
  /** @type {Found} */
263
263
  const foundReplace = {
@@ -270,7 +270,7 @@ const foundReplace = {
270
270
  }
271
271
 
272
272
  /** @type {<T>(leaf3: Array3<T>) => Result<T>} */
273
- const overflow = ([v0, v1, v2]) => ({ overflow: [[v0], v1, [v2]] })
273
+ const overflow = ([v0, v1, v2]) => ['overflow', [[v0], v1, [v2]]]
274
274
 
275
275
  /** @type {NotFound} */
276
276
  const notFoundInsert = {
@@ -340,7 +340,7 @@ module.exports = {
340
340
  */
341
341
  getVisitor: cmp => node => {
342
342
  const result = visit(getVisitor)(cmp)(() => { throw '' })(node)
343
- if ('done' in result && result.done) { return result.value }
343
+ if (result[0] === 'done') { return result[1] }
344
344
  return undefined
345
345
  },
346
346
  /** @readonly */
package/btree/test.js CHANGED
@@ -6,25 +6,26 @@ const list = require('../sequence')
6
6
  /** @type {(node: btree.Node<string>) => (value: string) => btree.Node<string>} */
7
7
  const set = node => value => {
8
8
  const result = setVisitor(cmp(value))(() => value)(node)
9
- if ('replace' in result) { return result.replace }
10
- if ('overflow' in result) { return result.overflow }
11
- return node
9
+ switch (result[0]) {
10
+ case 'replace': case 'overflow': { return result[1] }
11
+ default: { return node }
12
+ }
12
13
  }
13
14
 
14
15
  const test = () => {
15
16
  /** @type {btree.Node<string>} */
16
- let node = ['a']
17
- node = set(node)('b')
18
- node = set(node)('c')
19
- node = set(node)('d')
20
- node = set(node)('e')
21
- node = set(node)('f')
17
+ let _map = ['a']
18
+ _map = set(_map)('b')
19
+ _map = set(_map)('c')
20
+ _map = set(_map)('d')
21
+ _map = set(_map)('e')
22
+ _map = set(_map)('f')
22
23
  //
23
24
  {
24
25
  /** @type {import('../sequence').Result<string>} */
25
- let result = list.next(valuesList(node))
26
- while (result !== undefined) {
27
- result = list.next(result[1])
26
+ let _item = list.next(valuesList(_map))
27
+ while (_item !== undefined) {
28
+ _item = list.next(_item[1])
28
29
  }
29
30
  }
30
31
  }
package/cmp/index.js CHANGED
@@ -18,8 +18,8 @@ const index3 = cmp => value => /** @type {Index3} */ (cmp(value) + 1)
18
18
 
19
19
  /** @type {<T>(cmp: Cmp<T>) => (v2: Array2<T>) => Index5} */
20
20
  const index5 = cmp => ([v0, v1]) => {
21
- const i = cmp(v0)
22
- return /** @type {Index5} */ (i <= 0 ? i + 1 : cmp(v1) + 3)
21
+ const _0 = cmp(v0)
22
+ return /** @type {Index5} */ (_0 <= 0 ? _0 + 1 : cmp(v1) + 3)
23
23
  }
24
24
 
25
25
  /** @type {(a: string) => (b: string) => Sign} */
package/function/index.js CHANGED
@@ -7,9 +7,6 @@
7
7
  /** @type {<X, O>(f: Func<X, O>) => <I>(g: Func<I, X>) => Func<I, O>} */
8
8
  const combine = f => g => x => f(g(x))
9
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
10
  /** @type {<T>(value: T) => T} */
14
11
  const id = value => value
15
12
 
@@ -17,7 +14,5 @@ module.exports = {
17
14
  /** @readonly */
18
15
  id,
19
16
  /** @readonly */
20
- pipe,
21
- /** @readonly */
22
17
  combine,
23
18
  }
package/json/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  const seq = require('../sequence')
2
2
  const map = require('../map')
3
3
  const op = require('../sequence/operator')
4
+ const object = require('../object')
5
+ const array = require('../sequence/array')
4
6
 
5
7
  /**
6
8
  * @typedef {{
@@ -22,20 +24,44 @@ const addProperty = value => {
22
24
  const [name, tail] = result
23
25
  return { ...srcObject, [name]: f(tail)(srcObject[name]) }
24
26
  }
25
- return path => f(seq.fromArray(path))
27
+ return path => f(array.sequence(path))
26
28
  }
27
29
 
28
- /** @type {(kv: readonly[string, seq.Sequence<string>]) => seq.Sequence<string>} */
29
- const property = ([k, v]) => seq.concat(seq.list(JSON.stringify(k)), seq.list(':'), v)
30
+ /** @type {(_: string) => seq.Sequence<string>} */
31
+ const stringSerialize = input => seq.list(JSON.stringify(input))
32
+
33
+ /** @type {(_: number) => seq.Sequence<string>} */
34
+ const numberSerialize = input => seq.list(JSON.stringify(input))
35
+
36
+ const nullSerialize = seq.list('null')
37
+
38
+ const trueSerialize = seq.list('true')
39
+
40
+ const falseSerialize = seq.list('false')
41
+
42
+ /** @type {(_: boolean) => seq.Sequence<string>} */
43
+ const boolSerialize = value => value ? trueSerialize : falseSerialize
44
+
45
+ /** @type {(kv: readonly[string, Json]) => seq.Sequence<string>} */
46
+ const propertySerialize = ([k, v]) => seq.concat(
47
+ stringSerialize(k),
48
+ colon,
49
+ serialize(v))
50
+
51
+ const colon = seq.list(':')
52
+ const comma = seq.list(',')
30
53
 
31
54
  /** @type {op.Scan<seq.Sequence<string>, seq.Sequence<string>>} */
32
- const commaValue = a => [seq.concat(seq.list(','), a), commaValue]
55
+ const commaValue = a => [seq.concat(comma, a), commaValue]
33
56
 
34
57
  /** @type {op.Scan<seq.Sequence<string>, seq.Sequence<string>>} */
35
58
  const joinScan = value => [value, commaValue]
36
59
 
37
60
  /** @type {seq.SequenceMap<seq.Sequence<string>, string>} */
38
- const join = input => seq.flat(seq.scan(joinScan)(input))
61
+ const join = input => {
62
+ const _0 = seq.scan(joinScan)(input)
63
+ return seq.flat(_0)
64
+ }
39
65
 
40
66
  /** @type {(open: string) => (close: string) => (input: seq.Sequence<seq.Sequence<string>>) => seq.Sequence<string>} */
41
67
  const list = open => close => {
@@ -49,41 +75,54 @@ const objectList = list('{')('}')
49
75
  const arrayList = list('[')(']')
50
76
 
51
77
  /** @type {(object: Object) => seq.Sequence<string>} */
52
- const objectStringify = object => {
53
- /** @type {map.Map<seq.Sequence<string>>} */
54
- const m = seq.fold(m => ([k, v]) => m.set(k)(stringSeq(v)))(map.empty)(seq.fromArray(Object.entries(object)))
55
- return objectList(seq.map(property)(m.entries))
78
+ const objectSerialize = input => {
79
+ const _0 = object.entries(input)
80
+ const _1 = map.fromEntries(_0).entries
81
+ const _2 = seq.map(propertySerialize)(_1)
82
+ return objectList(_2)
56
83
  }
57
84
 
58
- /** @type {(array: Array) => seq.Sequence<string>} */
59
- const arrayStringify = array => arrayList(seq.map(stringSeq)(seq.fromArray(array)))
85
+ /** @type {(input: Array) => seq.Sequence<string>} */
86
+ const arraySerialize = input => {
87
+ const _0 = array.sequence(input)
88
+ const _1 = seq.map(serialize)(_0)
89
+ return arrayList(_1)
90
+ }
60
91
 
61
92
  /** @type {(value: Json) => seq.Sequence<string>} */
62
- const stringSeq = value => {
63
- const x = typeof value
93
+ const serialize = value => {
64
94
  switch (typeof value) {
65
- case 'boolean': { return seq.list(value ? "true" : "false") }
66
- // Note: we shouldn't use JSON.stringify since it has non determenistic behavior.
67
- // In particular: property order could be different.
68
- case 'number': case 'string': { return seq.list(JSON.stringify(value)) }
95
+ case 'boolean': { return boolSerialize(value) }
96
+ case 'number': { return numberSerialize(value) }
97
+ case 'string': { return stringSerialize(value) }
69
98
  default: {
70
- if (value === null) { return seq.list("null") }
71
- if (value instanceof Array) { return arrayStringify(value) }
72
- return objectStringify(value)
99
+ if (value === null) { return nullSerialize }
100
+ if (value instanceof Array) { return arraySerialize(value) }
101
+ return objectSerialize(value)
73
102
  }
74
103
  }
75
104
  }
76
105
 
77
106
  /**
78
- * A deterministic version of `JSON.stringify`
107
+ * A version of `JSON.stringify` with an alphabeticly ordered `keys`.
108
+ *
109
+ * The standard `JSON.stringify` rules determines by
110
+ * https://262.ecma-international.org/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys
79
111
  *
80
112
  * @type {(value: Json) => string}
81
113
  */
82
- const stringify = value => seq.join('')(stringSeq(value))
114
+ const stringify = value => seq.join('')(serialize(value))
115
+
116
+ /** @type {(value: string) => Json} */
117
+ const parse = value => JSON.parse(value)
83
118
 
84
119
  module.exports = {
85
120
  /** @readonly */
86
121
  addProperty,
87
122
  /** @readonly */
88
123
  stringify,
124
+ /** @readonly */
125
+ serialize,
126
+ /** @readonly */
127
+ parse,
89
128
  }
package/json/test.js CHANGED
@@ -13,6 +13,8 @@ if (json.addProperty("Hello")([])({}) !== "Hello") { throw 'error' }
13
13
  }
14
14
 
15
15
  {
16
- const x = json.stringify(json.addProperty("Hello")(['a', 'x'])({ a: { y: [24] }, c: [], b: 12 }))
17
- if (x !== '{"a":{"x":"Hello","y":[24]},"b":12,"c":[]}') { throw x }
16
+ const _0 = { a: { y: [24] }, c: [], b: 12 }
17
+ const _1 = json.addProperty("Hello")(['a', 'x'])(_0)
18
+ const _2 = json.stringify(_1)
19
+ if (_2 !== '{"a":{"x":"Hello","y":[24]},"b":12,"c":[]}') { throw _2 }
18
20
  }
package/map/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const option = require("../option")
2
- const { getVisitor, setVisitor, values: valuesList } = require("../btree")
2
+ const { getVisitor, setVisitor, values } = require("../btree")
3
3
  const { cmp } = require("../cmp")
4
4
  const seq = require("../sequence")
5
5
  const op = require("../sequence/operator")
@@ -44,11 +44,12 @@ const create = root => ({
44
44
  get: name => option.map(([,value]) => value)(getVisitor(keyCmp(name))(root)),
45
45
  set: name => value => {
46
46
  const result = setVisitor(keyCmp(name))(() => [name, value])(root)
47
- if ('replace' in result) { return create(result.replace) }
48
- if ('overflow' in result) { return create(result.overflow) }
49
- throw ''
47
+ switch (result[0]) {
48
+ case 'replace': case 'overflow': { return create(result[1]) }
49
+ default: { throw '' }
50
+ }
50
51
  },
51
- entries: valuesList(root),
52
+ entries: values(root),
52
53
  root,
53
54
  })
54
55
 
@@ -67,8 +68,14 @@ const empty = {
67
68
  root: undefined
68
69
  }
69
70
 
71
+ /** @type {<T>(map: Map<T>) => (entry: Entry<T>) => Map<T>} */
72
+ const setOperator = map => ([k, v]) => map.set(k)(v)
73
+
70
74
  /** @type {<T>(entries: seq.Sequence<Entry<T>>) => Map<T>} */
71
- const fromEntries = seq.fold(map => entry => map.set(entry))(empty)
75
+ const fromEntries = entries => {
76
+ /** @typedef {typeof entries extends seq.Sequence<Entry<infer T>> ? T : never} T */
77
+ return seq.fold(setOperator)(/** @type {Map<T>} */(empty))(entries)
78
+ }
72
79
 
73
80
  module.exports = {
74
81
  /** @readonly */
@@ -1,5 +1,5 @@
1
1
  const array = require('../sequence/array')
2
- const { pipe } = require('../function')
2
+ const { combine } = require('../function')
3
3
  const option = require('../option')
4
4
  const { head, last, splitLast, splitFirst } = array
5
5
  const iter = require('../sequence/iterable')
@@ -88,9 +88,9 @@ const external = packages => {
88
88
  const defined = ([first, tail]) => externalOrInternal(packages(first))(tail)
89
89
  /** @type {(_: Path) => readonly [string, Path]|undefined} */
90
90
  const sf = splitFirst
91
- return pipe
92
- (sf)
91
+ return combine
93
92
  (option.map(defined))
93
+ (sf)
94
94
  }
95
95
 
96
96
  /** @type {(_: Location) => (_: string) => Module|undefined} */
@@ -0,0 +1,17 @@
1
+ const array = require('../sequence/array')
2
+ const seq = require('../sequence')
3
+
4
+ /**
5
+ * @template T
6
+ * @typedef {{
7
+ * readonly [k in string]: T
8
+ * }} Object_
9
+ */
10
+
11
+ /** @type {<T>(object: Object_<T>) => seq.Sequence<readonly[string, T]>} */
12
+ const entries = object => array.sequence(Object.entries(object))
13
+
14
+ module.exports = {
15
+ /** @readonly */
16
+ entries,
17
+ }
package/package.json CHANGED
@@ -1,25 +1,25 @@
1
1
  {
2
- "name": "functionalscript",
3
- "version": "0.0.191",
4
- "description": "FunctionalScript is a functional subset of JavaScript",
5
- "main": "index.js",
6
- "scripts": {
7
- "tsc": "tsc",
8
- "test": "tsc && npm run test-only",
9
- "test-only": "node --trace-uncaught ./test"
10
- },
11
- "repository": {
12
- "type": "git",
13
- "url": "git+https://github.com/functionalscript/functionalscript.git"
14
- },
15
- "author": "Natfoam",
16
- "license": "Apache-2.0",
17
- "bugs": {
18
- "url": "https://github.com/functionalscript/functionalscript/issues"
19
- },
20
- "homepage": "https://github.com/functionalscript/functionalscript#readme",
21
- "devDependencies": {
22
- "@types/node": "^16.11.9",
23
- "typescript": "^4.5.2"
24
- }
2
+ "name": "functionalscript",
3
+ "version": "0.0.200",
4
+ "description": "FunctionalScript is a functional subset of JavaScript",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "tsc": "tsc",
8
+ "test": "tsc && npm run test-only",
9
+ "test-only": "node --trace-uncaught ./test"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/functionalscript/functionalscript.git"
14
+ },
15
+ "author": "Natfoam",
16
+ "license": "Apache-2.0",
17
+ "bugs": {
18
+ "url": "https://github.com/functionalscript/functionalscript/issues"
19
+ },
20
+ "homepage": "https://github.com/functionalscript/functionalscript#readme",
21
+ "devDependencies": {
22
+ "@types/node": "^16.11.9",
23
+ "typescript": "^4.5.2"
24
+ }
25
25
  }
@@ -1,4 +1,5 @@
1
1
  const option = require('../../option')
2
+ const seq = require('..')
2
3
 
3
4
  /**
4
5
  * @template T
@@ -86,15 +87,29 @@ const head = a => a.length === 0 ? undefined : uncheckHead(a)
86
87
 
87
88
  /** @type {<T>(_: Array<T>) => readonly [Array<T>, T]|undefined} */
88
89
  const splitLast = a => {
89
- /** @typedef {typeof a[0]} T*/
90
- /** @type {(_: T) => readonly [Array<T>, T]} */
91
- const split = x => [uncheckHead(a), x]
92
- return option.map(split)(last(a))
90
+ const lastA = last(a)
91
+ if (lastA === undefined) { return undefined }
92
+ return [uncheckHead(a), lastA]
93
93
  }
94
94
 
95
95
  /** @type {(index: number) => <T>(a: Array<T>) => readonly[T]|undefined} */
96
96
  const at = index => a => index < a.length ? [a[index]] : undefined
97
97
 
98
+ /** @type {<T>(array: Array<T>) => seq.Sequence<T>} */
99
+ const sequence = a => {
100
+ /** @typedef {typeof a extends Array<infer T> ? T : never} T */
101
+ /** @type {(index: number) => seq.Sequence<T>} */
102
+ const seq = index => () => {
103
+ const result = at(index)(a)
104
+ if (result === undefined) { return undefined }
105
+ return [result[0], seq(index + 1)]
106
+ }
107
+ return seq(0)
108
+ }
109
+
110
+ /** @type {<T>(list: seq.Sequence<T>) => readonly T[]} */
111
+ const fromSequence = input => Array.from(seq.iterable(input))
112
+
98
113
  module.exports = {
99
114
  /** @readonly */
100
115
  at,
@@ -110,4 +125,8 @@ module.exports = {
110
125
  splitFirst,
111
126
  /** @readonly */
112
127
  splitLast,
128
+ /** @readonly */
129
+ sequence,
130
+ /** @readonly */
131
+ fromSequence,
113
132
  }
@@ -1,4 +1,4 @@
1
- const { pipe } = require('../../function')
1
+ const { combine } = require('../../function')
2
2
  const seq = require('../operator')
3
3
 
4
4
  /**
@@ -69,7 +69,7 @@ const reduce = ([first, s]) => async c => {
69
69
 
70
70
  const sum = reduce(seq.sum)
71
71
 
72
- const join = pipe(seq.join)(reduce)
72
+ const join = combine(reduce)(seq.join)
73
73
 
74
74
  const length = reduce(seq.length)
75
75
 
package/sequence/index.js CHANGED
@@ -1,6 +1,5 @@
1
- const array = require('./array')
2
1
  const seqOp = require('./operator')
3
- const { pipe } = require('../function')
2
+ const { combine } = require('../function')
4
3
  const op = require('../function/operator')
5
4
  const { logicalNot, strictEqual } = require('../function/operator')
6
5
 
@@ -33,7 +32,7 @@ const { logicalNot, strictEqual } = require('../function/operator')
33
32
 
34
33
  /**
35
34
  * @template T
36
- * @typedef {array.Tuple2<T, Sequence<T>>} FirstAndTail
35
+ * @typedef {readonly[T, Sequence<T>]} FirstAndTail
37
36
  */
38
37
 
39
38
  const empty = () => undefined
@@ -78,31 +77,23 @@ const first = input => {
78
77
  * @typedef {(list: Sequence<T>) => R} SequenceReduce
79
78
  */
80
79
 
81
- /** @type {<T>(...array: readonly T[]) => Sequence<T>} */
80
+ /**
81
+ * Note: the operation is not lazy. It traverse the given array and creates a linked list.
82
+ *
83
+ * @type {<T>(...array: readonly T[]) => Sequence<T>}
84
+ */
82
85
  const list = (...array) => {
83
86
  /** @typedef {typeof array extends readonly(infer T)[] ? T : never} T */
84
87
  let i = array.length
85
88
  /** @type {Sequence<T>} */
86
- let tail = empty
87
- while (true) {
88
- if (i === 0) { return tail }
89
+ let result = empty
90
+ while (i !== 0) {
89
91
  i = i - 1
90
92
  /** @type {FirstAndTail<T>} */
91
- const result = [array[i], tail]
92
- tail = () => result
93
- }
94
- }
95
-
96
- /** @type {<T>(array: array.Array<T>) => Sequence<T>} */
97
- const fromArray = a => {
98
- /** @typedef {typeof a extends array.Array<infer T> ? T : never} T */
99
- /** @type {(index: number) => Sequence<T>} */
100
- const at = index => () => {
101
- const result = array.at(index)(a)
102
- if (result === undefined) { return undefined }
103
- return [result[0], at(index + 1)]
93
+ const listResult = [array[i], result]
94
+ result = () => listResult
104
95
  }
105
- return at(0)
96
+ return result
106
97
  }
107
98
 
108
99
  /** @type {<T>(...array: readonly Sequence<T>[]) => Sequence<T>} */
@@ -110,12 +101,12 @@ const concat = (...array) => {
110
101
  let i = array.length
111
102
  if (i == 0) { return empty }
112
103
  i = i - 1
113
- let tail = array[i]
114
- while (true) {
115
- if (i === 0) { return tail }
104
+ let result = array[i]
105
+ while (i !== 0) {
116
106
  i = i - 1
117
- tail = [array[i], tail]
107
+ result = [array[i], result]
118
108
  }
109
+ return result
119
110
  }
120
111
 
121
112
  /** @type {(_: number) => Sequence<number>} */
@@ -202,7 +193,8 @@ const sum = reduce(seqOp.sum)
202
193
 
203
194
  const length = reduce(seqOp.length)
204
195
 
205
- const join = pipe(seqOp.join)(reduce)
196
+ /** @type {(separator: string) => SequenceReduce<string, string>} */
197
+ const join = separator => reduce(seqOp.join(separator))
206
198
 
207
199
  /** @type {<T>(f: (value: T) => boolean) => SequenceMap<T, T>} */
208
200
  const takeWhile = f => input => () => {
@@ -236,7 +228,7 @@ const some = f => input => find(x => x)(map(f)(input)) !== undefined
236
228
  const includes = value => some(strictEqual(value))
237
229
 
238
230
  /** @type {<T>(f: (value: T) => boolean) => SequenceReduce<T, boolean>} */
239
- const every = f => input => !some(pipe(f)(logicalNot))(input)
231
+ const every = f => input => !some(combine(logicalNot)(f))(input)
240
232
 
241
233
  /** @type {<T>(list: Sequence<T>) => Iterable<T>} */
242
234
  const iterable = list => ({
@@ -264,7 +256,7 @@ const asyncIterable = list => ({
264
256
  }
265
257
  })
266
258
 
267
- /** @type {<A>(a: Sequence<A>) => <B>(b: Sequence<B>) => Sequence<array.Tuple2<A, B>>} */
259
+ /** @type {<A>(a: Sequence<A>) => <B>(b: Sequence<B>) => Sequence<readonly[A, B]>} */
268
260
  const zip = a => b => () => {
269
261
  const resultA = next(a)
270
262
  if (resultA === undefined) { return undefined }
@@ -273,9 +265,6 @@ const zip = a => b => () => {
273
265
  return [[resultA[0], resultB[0]], zip(resultA[1])(resultB[1])]
274
266
  }
275
267
 
276
- /** @type {<T>(list: Sequence<T>) => readonly T[]} */
277
- const toArray = input => Array.from(iterable(input))
278
-
279
268
  module.exports = {
280
269
  /** @readonly */
281
270
  next,
@@ -292,10 +281,6 @@ module.exports = {
292
281
  /** @readonly */
293
282
  first,
294
283
  /** @readonly */
295
- fromArray,
296
- /** @readonly */
297
- toArray,
298
- /** @readonly */
299
284
  iterable,
300
285
  /** @readonly */
301
286
  asyncIterable,
@@ -1,4 +1,5 @@
1
- const { pipe } = require('../../function')
1
+ const { iterable } = require('..')
2
+ const { combine } = require('../../function')
2
3
  const seq = require('../operator')
3
4
 
4
5
  /** @type {<T>(a: Iterable<T>) => (b: Iterable<T>) => Iterable<T>} */
@@ -39,7 +40,7 @@ const sum = reduce(seq.sum)
39
40
 
40
41
  const length = reduce(seq.length)
41
42
 
42
- const join = pipe(seq.join)(reduce)
43
+ const join = combine(reduce)(seq.join)
43
44
 
44
45
  /** @type {<T, R>(f: (value: T) => Iterable<R>) => (c: Iterable<T>) => Iterable<R>} */
45
46
  const flatMap = f => c => ({
@@ -1,5 +1,5 @@
1
1
  const i = require('.')
2
- const { pipe } = require('../../function')
2
+ const { combine } = require('../../function')
3
3
 
4
4
  {
5
5
  const r = i.sum([120, 300, 42])
@@ -33,9 +33,9 @@ const { pipe } = require('../../function')
33
33
  /** @type {(_: string) => string|undefined} */
34
34
  const file = _ => 'x'
35
35
  /** @type {(_: string) => string|undefined} */
36
- const x = p => pipe
37
- (i.map(x => file(x())))
36
+ const x = p => combine
38
37
  (i.find(x => x !== undefined))
38
+ (i.map(x => file(x())))
39
39
  ([() => p, () => `${p}.js`, () => `${p}/index.js`])
40
40
  if (x('index.js') !== 'x') { throw 'error' }
41
41
  }
package/sequence/test.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const seq = require('.')
2
2
  const { sum } = require('./operator')
3
3
  const op = require('./operator')
4
+ const array = require('./array')
4
5
 
5
6
  /** @type {<T>(input: seq.Sequence<T>) => void} */
6
7
  const print = input => {
@@ -14,9 +15,9 @@ const print = input => {
14
15
  }
15
16
 
16
17
  {
17
- const big = seq.fromArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 42, 60])
18
- const list0 = seq.fromArray([0, 1, 2, 3])
19
- const list1 = seq.flatMap(x => seq.fromArray([x, x * 2, x * 3]))(list0)
18
+ const big = seq.list(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 42, 60)
19
+ const list0 = seq.list(0, 1, 2, 3)
20
+ const list1 = seq.flatMap(x => seq.list(x, x * 2, x * 3))(list0)
20
21
  const list2 = seq.concat(list0, list0)
21
22
  const list3 = seq.exclusiveScan(sum)(list0)
22
23
  const r = seq.find(x => x === 42)(big)
@@ -26,15 +27,18 @@ const print = input => {
26
27
  if (seq.some(x => x > 50)(big) !== true) { throw 'x' }
27
28
  if (seq.first(seq.drop(16)(big)) !== 42) { throw 'drop'}
28
29
  {
29
- const a = seq.toArray(seq.generate(1_000_000))
30
- let x = seq.concat(seq.fromArray(a), big)
30
+ const a = seq.map(seq.generate)(seq.generate(100_000))
31
+ const ar = array.fromSequence(a)
32
+ // This operation use a lot of stack because `...`
33
+ // puts array items on a stack.
34
+ // Use `array.sequence` instead
35
+ const x = seq.concat(...ar)
31
36
  const r = seq.next(x)
32
37
  // print(x)
33
38
  }
34
39
  {
35
- const a = seq.map(seq.generate)(seq.generate(100_000))
36
- const array = seq.toArray(a)
37
- const x = seq.concat(...array)
40
+ const a = array.fromSequence(seq.generate(1_000_000))
41
+ let x = seq.concat(array.sequence(a), big)
38
42
  const r = seq.next(x)
39
43
  // print(x)
40
44
  }
@@ -57,6 +61,6 @@ const print = input => {
57
61
  }
58
62
 
59
63
  {
60
- const x = seq.join(':')(seq.fromArray(["1", "2", "3", "4", "5", "6"]))
64
+ const x = seq.join(':')(seq.list("1", "2", "3", "4", "5", "6"))
61
65
  if (x !== "1:2:3:4:5:6") { throw x }
62
66
  }
package/version.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const cp = require('child_process')
2
2
  const fs = require('fs')
3
+ const json = require('./json')
3
4
 
4
5
  const b =cp.execSync('git log --oneline')
5
6
 
@@ -9,8 +10,8 @@ const v = `0.0.${r}`
9
10
 
10
11
  console.log(`version: ${v}`)
11
12
 
12
- const package_json = JSON.parse(fs.readFileSync('package.json').toString())
13
+ let package_json = json.parse(fs.readFileSync('package.json').toString())
13
14
 
14
- package_json.version = v
15
+ package_json = json.addProperty(v)(['version'])(package_json)
15
16
 
16
- fs.writeFileSync('package.json', JSON.stringify(package_json, null, 2))
17
+ fs.writeFileSync('package.json', JSON.stringify(package_json, null, 3))