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 +15 -18
- package/btree/test.js +10 -10
- package/cmp/index.js +2 -2
- package/function/index.js +0 -5
- package/json/index.js +63 -27
- package/json/test.js +4 -2
- package/map/index.js +20 -8
- package/module-manager/index.js +3 -3
- package/object/index.js +17 -0
- package/package.json +23 -23
- package/sequence/array/index.js +23 -4
- package/sequence/asyncIterable/index.js +2 -2
- package/sequence/index.js +54 -34
- package/sequence/iterable/index.js +3 -2
- package/sequence/iterable/test.js +3 -3
- package/sequence/test.js +24 -9
- package/version.js +4 -3
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
|
|
309
|
+
const values = node => () => {
|
|
313
310
|
const f = () => {
|
|
314
311
|
switch (node.length) {
|
|
315
|
-
case 1: case 2: { return seq.
|
|
312
|
+
case 1: case 2: { return seq.list(...node) }
|
|
316
313
|
case 3: {
|
|
317
|
-
return
|
|
318
|
-
|
|
319
|
-
seq.
|
|
320
|
-
|
|
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
|
|
325
|
-
|
|
326
|
-
seq.
|
|
327
|
-
|
|
328
|
-
seq.
|
|
329
|
-
|
|
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
|
-
|
|
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
|
|
346
|
-
if ('done' in
|
|
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
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
|
26
|
-
while (
|
|
27
|
-
|
|
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
|
|
22
|
-
return /** @type {Index5} */ (
|
|
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(
|
|
27
|
+
return path => f(array.sequence(path))
|
|
26
28
|
}
|
|
27
29
|
|
|
28
|
-
/** @type {(
|
|
29
|
-
const
|
|
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(
|
|
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 =>
|
|
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.
|
|
43
|
-
const seqClose = seq.
|
|
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
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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 {(
|
|
62
|
-
const
|
|
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
|
|
66
|
-
const x = typeof value
|
|
93
|
+
const serialize = value => {
|
|
67
94
|
switch (typeof value) {
|
|
68
|
-
case 'boolean': { return
|
|
69
|
-
|
|
70
|
-
|
|
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
|
|
74
|
-
if (value instanceof Array) { return
|
|
75
|
-
return
|
|
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
|
|
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('')(
|
|
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
|
|
17
|
-
|
|
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,
|
|
2
|
+
const { getVisitor, setVisitor, values } = require("../btree")
|
|
3
3
|
const { cmp } = require("../cmp")
|
|
4
|
-
const
|
|
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:
|
|
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
|
|
46
|
-
if ('replace' in
|
|
47
|
-
if ('overflow' in
|
|
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:
|
|
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:
|
|
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
|
}
|
package/module-manager/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const array = require('../sequence/array')
|
|
2
|
-
const {
|
|
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
|
|
92
|
-
(sf)
|
|
91
|
+
return combine
|
|
93
92
|
(option.map(defined))
|
|
93
|
+
(sf)
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
/** @type {(_: Location) => (_: string) => Module|undefined} */
|
package/object/index.js
ADDED
|
@@ -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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
}
|
package/sequence/array/index.js
CHANGED
|
@@ -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
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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 {
|
|
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 =
|
|
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 {
|
|
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 {
|
|
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
|
-
/**
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
/** @
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
|
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 = (...
|
|
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 =>
|
|
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) ?
|
|
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
|
|
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
|
-
|
|
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(
|
|
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<
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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 =
|
|
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 {
|
|
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 =>
|
|
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
|
-
|
|
12
|
+
console.log(result[0])
|
|
12
13
|
i = result[1]
|
|
13
14
|
}
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
{
|
|
17
|
-
const big = seq.
|
|
18
|
-
const list0 = seq.
|
|
19
|
-
const list1 = seq.flatMap(x => seq.
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
13
|
+
let package_json = json.parse(fs.readFileSync('package.json').toString())
|
|
13
14
|
|
|
14
|
-
package_json
|
|
15
|
+
package_json = json.addProperty(v)(['version'])(package_json)
|
|
15
16
|
|
|
16
|
-
fs.writeFileSync('package.json', JSON.stringify(package_json, null,
|
|
17
|
+
fs.writeFileSync('package.json', JSON.stringify(package_json, null, 3))
|