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 +25 -25
- package/btree/test.js +13 -12
- package/cmp/index.js +2 -2
- package/function/index.js +0 -5
- package/json/index.js +61 -22
- package/json/test.js +4 -2
- package/map/index.js +13 -6
- 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 +20 -35
- package/sequence/iterable/index.js +3 -2
- package/sequence/iterable/test.js +3 -3
- package/sequence/test.js +13 -9
- package/version.js +4 -3
package/btree/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
const
|
|
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 {
|
|
12
|
+
* @typedef {cmp.Cmp<T>} Cmp
|
|
12
13
|
*/
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* @template T
|
|
16
|
-
* @typedef {
|
|
17
|
+
* @typedef {readonly[T]} Array1
|
|
17
18
|
*/
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* @template T
|
|
21
|
-
* @typedef {
|
|
22
|
+
* @typedef {readonly[T,T]} Array2
|
|
22
23
|
*/
|
|
23
24
|
|
|
24
25
|
/**
|
|
25
26
|
* @template T
|
|
26
|
-
* @typedef {
|
|
27
|
+
* @typedef {readonly[T,T,T]} Array3
|
|
27
28
|
*/
|
|
28
29
|
|
|
29
|
-
/** @typedef {
|
|
30
|
+
/** @typedef {0|1} Index2 */
|
|
30
31
|
|
|
31
|
-
/** @typedef {
|
|
32
|
+
/** @typedef {0|1|2} Index3 */
|
|
32
33
|
|
|
33
|
-
/** @typedef {
|
|
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 {
|
|
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 {
|
|
77
|
+
* @typedef {readonly['replace', Node<T>]} Replace
|
|
80
78
|
*/
|
|
81
79
|
|
|
82
80
|
/**
|
|
83
81
|
* @template T
|
|
84
|
-
* @typedef {
|
|
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
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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 =>
|
|
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 =>
|
|
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 =>
|
|
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 = () => () =>
|
|
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 =>
|
|
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]) =>
|
|
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 (
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
|
26
|
-
while (
|
|
27
|
-
|
|
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
|
|
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,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(
|
|
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 => {
|
|
@@ -49,41 +75,54 @@ const objectList = list('{')('}')
|
|
|
49
75
|
const arrayList = list('[')(']')
|
|
50
76
|
|
|
51
77
|
/** @type {(object: Object) => seq.Sequence<string>} */
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
|
|
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 {(
|
|
59
|
-
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
|
+
}
|
|
60
91
|
|
|
61
92
|
/** @type {(value: Json) => seq.Sequence<string>} */
|
|
62
|
-
const
|
|
63
|
-
const x = typeof value
|
|
93
|
+
const serialize = value => {
|
|
64
94
|
switch (typeof value) {
|
|
65
|
-
case 'boolean': { return
|
|
66
|
-
|
|
67
|
-
|
|
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
|
|
71
|
-
if (value instanceof Array) { return
|
|
72
|
-
return
|
|
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
|
|
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('')(
|
|
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
|
|
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,5 +1,5 @@
|
|
|
1
1
|
const option = require("../option")
|
|
2
|
-
const { getVisitor, setVisitor, values
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
switch (result[0]) {
|
|
48
|
+
case 'replace': case 'overflow': { return create(result[1]) }
|
|
49
|
+
default: { throw '' }
|
|
50
|
+
}
|
|
50
51
|
},
|
|
51
|
-
entries:
|
|
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 =
|
|
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 */
|
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.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
|
}
|
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,5 @@
|
|
|
1
|
-
const array = require('./array')
|
|
2
1
|
const seqOp = require('./operator')
|
|
3
|
-
const {
|
|
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 {
|
|
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
|
-
/**
|
|
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
|
|
87
|
-
while (
|
|
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
|
|
92
|
-
|
|
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
|
|
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
|
|
114
|
-
while (
|
|
115
|
-
if (i === 0) { return tail }
|
|
104
|
+
let result = array[i]
|
|
105
|
+
while (i !== 0) {
|
|
116
106
|
i = i - 1
|
|
117
|
-
|
|
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
|
-
|
|
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(
|
|
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<
|
|
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 {
|
|
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 => {
|
|
@@ -14,9 +15,9 @@ const print = input => {
|
|
|
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)
|
|
@@ -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.
|
|
30
|
-
|
|
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 =
|
|
36
|
-
|
|
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.
|
|
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
|
-
|
|
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))
|