functionalscript 0.0.190 → 0.0.198

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,14 +333,14 @@ 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 }
343
340
  */
344
341
  getVisitor: cmp => node => {
345
- const result = visit(getVisitor)(cmp)(() => { throw '' })(node)
346
- if ('done' in result && result.done) { return result.value }
342
+ const _0 = visit(getVisitor)(cmp)(() => { throw '' })(node)
343
+ if ('done' in _0 && _0.done) { return _0.value }
347
344
  return undefined
348
345
  },
349
346
  /** @readonly */
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
 
@@ -13,18 +13,18 @@ const set = node => value => {
13
13
 
14
14
  const test = () => {
15
15
  /** @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')
16
+ let _map = ['a']
17
+ _map = set(_map)('b')
18
+ _map = set(_map)('c')
19
+ _map = set(_map)('d')
20
+ _map = set(_map)('e')
21
+ _map = set(_map)('f')
22
22
  //
23
23
  {
24
24
  /** @type {import('../sequence').Result<string>} */
25
- let result = list.next(valuesList(node))
26
- while (result !== undefined) {
27
- result = list.next(result[1])
25
+ let _item = list.next(valuesList(_map))
26
+ while (_item !== undefined) {
27
+ _item = list.next(_item[1])
28
28
  }
29
29
  }
30
30
  }
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,25 +24,49 @@ 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.one(JSON.stringify(k)), seq.one(':'), 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.one(','), 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 => {
42
- const seqOpen = seq.one(open)
43
- const seqClose = seq.one(close)
68
+ const seqOpen = seq.list(open)
69
+ const seqClose = seq.list(close)
44
70
  return input => seq.concat(seqOpen, join(input), seqClose)
45
71
  }
46
72
 
@@ -49,44 +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
- let m = map.empty
55
- for (const [k, v] of Object.entries(object)) {
56
- m = m.set(k)(stringSeq(v))
57
- }
58
- 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)
59
83
  }
60
84
 
61
- /** @type {(array: Array) => seq.Sequence<string>} */
62
- 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
+ }
63
91
 
64
92
  /** @type {(value: Json) => seq.Sequence<string>} */
65
- const stringSeq = value => {
66
- const x = typeof value
93
+ const serialize = value => {
67
94
  switch (typeof value) {
68
- case 'boolean': { return seq.one(value ? "true" : "false") }
69
- // Note: we shouldn't use JSON.stringify since it has non determenistic behavior.
70
- // In particular: property order could be different.
71
- case 'number': case 'string': { return seq.one(JSON.stringify(value)) }
95
+ case 'boolean': { return boolSerialize(value) }
96
+ case 'number': { return numberSerialize(value) }
97
+ case 'string': { return stringSerialize(value) }
72
98
  default: {
73
- if (value === null) { return seq.one("null") }
74
- if (value instanceof Array) { return arrayStringify(value) }
75
- return objectStringify(value)
99
+ if (value === null) { return nullSerialize }
100
+ if (value instanceof Array) { return arraySerialize(value) }
101
+ return objectSerialize(value)
76
102
  }
77
103
  }
78
104
  }
79
105
 
80
106
  /**
81
- * 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
82
111
  *
83
112
  * @type {(value: Json) => string}
84
113
  */
85
- 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)
86
118
 
87
119
  module.exports = {
88
120
  /** @readonly */
89
121
  addProperty,
90
122
  /** @readonly */
91
123
  stringify,
124
+ /** @readonly */
125
+ serialize,
126
+ /** @readonly */
127
+ parse,
92
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,7 +1,8 @@
1
1
  const option = require("../option")
2
- const { getVisitor, setVisitor, valuesList } = require("../btree")
2
+ const { getVisitor, setVisitor, values } = 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
  */
@@ -42,12 +43,12 @@ const keyCmp = a => ([b]) => cmp(a)(b)
42
43
  const create = root => ({
43
44
  get: name => option.map(([,value]) => value)(getVisitor(keyCmp(name))(root)),
44
45
  set: name => value => {
45
- const result = setVisitor(keyCmp(name))(() => [name, value])(root)
46
- if ('replace' in result) { return create(result.replace) }
47
- if ('overflow' in result) { return create(result.overflow) }
46
+ const _0 = setVisitor(keyCmp(name))(() => [name, value])(root)
47
+ if ('replace' in _0) { return create(_0.replace) }
48
+ if ('overflow' in _0) { return create(_0.overflow) }
48
49
  throw ''
49
50
  },
50
- entries: valuesList(root),
51
+ entries: values(root),
51
52
  root,
52
53
  })
53
54
 
@@ -62,11 +63,22 @@ 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>(map: Map<T>) => (entry: Entry<T>) => Map<T>} */
71
+ const setOperator = map => ([k, v]) => map.set(k)(v)
72
+
73
+ /** @type {<T>(entries: seq.Sequence<Entry<T>>) => Map<T>} */
74
+ const fromEntries = entries => {
75
+ /** @typedef {typeof entries extends seq.Sequence<Entry<infer T>> ? T : never} T */
76
+ return seq.fold(setOperator)(/** @type {Map<T>} */(empty))(entries)
77
+ }
78
+
69
79
  module.exports = {
70
80
  /** @readonly */
71
81
  empty,
82
+ /** @readonly */
83
+ fromEntries,
72
84
  }
@@ -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.190",
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.198",
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,6 @@
1
- const array = require('./array')
2
1
  const seqOp = require('./operator')
3
- const { pipe } = require('../function')
2
+ const { combine } = require('../function')
3
+ const op = require('../function/operator')
4
4
  const { logicalNot, strictEqual } = require('../function/operator')
5
5
 
6
6
  /**
@@ -32,7 +32,7 @@ const { logicalNot, strictEqual } = require('../function/operator')
32
32
 
33
33
  /**
34
34
  * @template T
35
- * @typedef {array.Tuple2<T, Sequence<T>>} FirstAndTail
35
+ * @typedef {readonly[T, Sequence<T>]} FirstAndTail
36
36
  */
37
37
 
38
38
  const empty = () => undefined
@@ -77,26 +77,47 @@ const first = input => {
77
77
  * @typedef {(list: Sequence<T>) => R} SequenceReduce
78
78
  */
79
79
 
80
- /** @type {<T>(first: T) => Sequence<T>} */
81
- const one = first => () => [first, empty]
82
-
83
- /** @type {<T>(array: array.Array<T>) => Sequence<T>} */
84
- const fromArray = a => {
85
- /** @typedef {typeof a extends array.Array<infer T> ? T : never} T */
86
- /** @type {(index: number) => Sequence<T>} */
87
- const at = index => () => {
88
- const result = array.at(index)(a)
89
- if (result === undefined) { return undefined }
90
- return [result[0], at(index + 1)]
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
+ */
85
+ const list = (...array) => {
86
+ /** @typedef {typeof array extends readonly(infer T)[] ? T : never} T */
87
+ let i = array.length
88
+ /** @type {Sequence<T>} */
89
+ let result = empty
90
+ while (i !== 0) {
91
+ i = i - 1
92
+ /** @type {FirstAndTail<T>} */
93
+ const listResult = [array[i], result]
94
+ result = () => listResult
91
95
  }
92
- return at(0)
96
+ return result
93
97
  }
94
98
 
95
- /** @type {<T>(a: Sequence<T>) => SequenceMap<T, T>} */
96
- const concat2 = a => b => [a, b]
97
-
98
99
  /** @type {<T>(...array: readonly Sequence<T>[]) => Sequence<T>} */
99
- const concat = (...a) => flat(fromArray(a))
100
+ const concat = (...array) => {
101
+ let i = array.length
102
+ if (i == 0) { return empty }
103
+ i = i - 1
104
+ let result = array[i]
105
+ while (i !== 0) {
106
+ i = i - 1
107
+ result = [array[i], result]
108
+ }
109
+ return result
110
+ }
111
+
112
+ /** @type {(_: number) => Sequence<number>} */
113
+ const generate = n => {
114
+ /** @type {(_: number) => Sequence<number>} */
115
+ const f = i => () => {
116
+ if (n <= i) { return undefined }
117
+ return [i, f(i + 1)]
118
+ }
119
+ return f(0)
120
+ }
100
121
 
101
122
  /** @type {<T, R>(f: (value: T) => Sequence<R>) => SequenceMap<T, R>} */
102
123
  const flatMap = f => input => () => {
@@ -117,16 +138,16 @@ const flatMap = f => input => () => {
117
138
  const flat = flatMap(i => i)
118
139
 
119
140
  /** @type {<T, R>(f: (value: T) => R) => SequenceMap<T, R>} */
120
- const map = f => flatMap(i => one(f(i)))
141
+ const map = f => flatMap(i => list(f(i)))
121
142
 
122
143
  /** @type {<T>(f: (value: T) => boolean) => SequenceMap<T, T>} */
123
- const filter = f => flatMap(i => f(i) ? one(i) : empty)
144
+ const filter = f => flatMap(i => f(i) ? list(i) : empty)
124
145
 
125
146
  /** @type {<T, R>(f: (value: T) => R|undefined) => (value: T) => Sequence<R>} */
126
147
  const filterMapFunc = f => i => {
127
148
  const result = f(i)
128
149
  if (result === undefined) { return empty }
129
- return one(result)
150
+ return list(result)
130
151
  }
131
152
 
132
153
  /** @type {<T, R>(f: (value: T) => R|undefined) => SequenceMap<T, R>} */
@@ -163,13 +184,17 @@ const last = def => input => {
163
184
  /** @type {<T, R>(s: seqOp.ExclusiveScan<T, R>) => (input: Sequence<T>) => R} */
164
185
  const reduce = ([first, s]) => input => last(first)(scan(s)(input))
165
186
 
187
+ /** @type {<T, R>(ro: op.ReduceOperator<R, T>) => (first: R) => (input: Sequence<T>) => R} */
188
+ const fold = ro => first => reduce(seqOp.exclusiveScan(ro)(first))
189
+
166
190
  const entries = scan(seqOp.entries)
167
191
 
168
192
  const sum = reduce(seqOp.sum)
169
193
 
170
194
  const length = reduce(seqOp.length)
171
195
 
172
- const join = pipe(seqOp.join)(reduce)
196
+ /** @type {(separator: string) => SequenceReduce<string, string>} */
197
+ const join = separator => reduce(seqOp.join(separator))
173
198
 
174
199
  /** @type {<T>(f: (value: T) => boolean) => SequenceMap<T, T>} */
175
200
  const takeWhile = f => input => () => {
@@ -203,7 +228,7 @@ const some = f => input => find(x => x)(map(f)(input)) !== undefined
203
228
  const includes = value => some(strictEqual(value))
204
229
 
205
230
  /** @type {<T>(f: (value: T) => boolean) => SequenceReduce<T, boolean>} */
206
- const every = f => input => !some(pipe(f)(logicalNot))(input)
231
+ const every = f => input => !some(combine(logicalNot)(f))(input)
207
232
 
208
233
  /** @type {<T>(list: Sequence<T>) => Iterable<T>} */
209
234
  const iterable = list => ({
@@ -231,7 +256,7 @@ const asyncIterable = list => ({
231
256
  }
232
257
  })
233
258
 
234
- /** @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]>} */
235
260
  const zip = a => b => () => {
236
261
  const resultA = next(a)
237
262
  if (resultA === undefined) { return undefined }
@@ -240,14 +265,11 @@ const zip = a => b => () => {
240
265
  return [[resultA[0], resultB[0]], zip(resultA[1])(resultB[1])]
241
266
  }
242
267
 
243
- /** @type {<T>(list: Sequence<T>) => readonly T[]} */
244
- const toArray = input => Array.from(iterable(input))
245
-
246
268
  module.exports = {
247
269
  /** @readonly */
248
270
  next,
249
271
  /** @readonly */
250
- one,
272
+ list,
251
273
  /** @readonly */
252
274
  empty,
253
275
  /** @readonly */
@@ -255,14 +277,10 @@ module.exports = {
255
277
  /** @readonly */
256
278
  concat,
257
279
  /** @readonly */
258
- concat2,
280
+ generate,
259
281
  /** @readonly */
260
282
  first,
261
283
  /** @readonly */
262
- fromArray,
263
- /** @readonly */
264
- toArray,
265
- /** @readonly */
266
284
  iterable,
267
285
  /** @readonly */
268
286
  asyncIterable,
@@ -283,6 +301,8 @@ module.exports = {
283
301
  /** @readonly */
284
302
  last,
285
303
  /** @readonly */
304
+ fold,
305
+ /** @readonly */
286
306
  reduce,
287
307
  /** @readonly */
288
308
  entries,
@@ -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 => {
@@ -8,15 +9,15 @@ const print = input => {
8
9
  while (true) {
9
10
  const result = seq.next(i)
10
11
  if (result === undefined) { return }
11
- // console.log(result[0])
12
+ console.log(result[0])
12
13
  i = result[1]
13
14
  }
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)
@@ -25,11 +26,26 @@ const print = input => {
25
26
  if (seq.some(x => x > 100)(big) !== false) { throw 'x' }
26
27
  if (seq.some(x => x > 50)(big) !== true) { throw 'x' }
27
28
  if (seq.first(seq.drop(16)(big)) !== 42) { throw 'drop'}
29
+ {
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)
36
+ const r = seq.next(x)
37
+ // print(x)
38
+ }
39
+ {
40
+ const a = array.fromSequence(seq.generate(1_000_000))
41
+ let x = seq.concat(array.sequence(a), big)
42
+ const r = seq.next(x)
43
+ // print(x)
44
+ }
28
45
  {
29
46
  let x = big
30
47
  for (let i = 0; i < 1_000_000; ++i) {
31
- // concat() still causes a stack overflow
32
- x = seq.concat2(seq.empty)(x)
48
+ x = seq.concat(seq.empty, x)
33
49
  }
34
50
  const r = seq.next(x)
35
51
  // print(x)
@@ -37,8 +53,7 @@ const print = input => {
37
53
  {
38
54
  let x = big
39
55
  for (let i = 0; i < 1_000_000; ++i) {
40
- // concat() still causes a stack overflow
41
- x = seq.concat2(x)(seq.one(i))
56
+ x = seq.concat(x, seq.list(i))
42
57
  }
43
58
  const r = seq.next(x)
44
59
  // print(x)
@@ -46,6 +61,6 @@ const print = input => {
46
61
  }
47
62
 
48
63
  {
49
- 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"))
50
65
  if (x !== "1:2:3:4:5:6") { throw x }
51
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))