functionalscript 0.0.214 → 0.0.218
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 +4 -4
- package/btree/test.js +1 -1
- package/function/index.js +8 -4
- package/json/index.js +25 -25
- package/json/test.js +6 -5
- package/map/index.js +5 -3
- package/module-manager/index.js +2 -6
- package/object/index.js +0 -5
- package/package.json +2 -2
- package/sequence/README.md +16 -1
- package/sequence/array/index.js +0 -19
- package/sequence/asyncIterable/index.js +1 -1
- package/sequence/index.js +204 -235
- package/sequence/iterable/index.js +1 -1
- package/sequence/iterable/test.js +2 -2
- package/sequence/operator/index.js +1 -1
- package/sequence/test.js +125 -57
- package/test.js +3 -3
package/btree/index.js
CHANGED
|
@@ -309,20 +309,20 @@ const replaceVisitor = {
|
|
|
309
309
|
const values = node => () => {
|
|
310
310
|
const f = () => {
|
|
311
311
|
switch (node.length) {
|
|
312
|
-
case 1: case 2: { return
|
|
312
|
+
case 1: case 2: { return node }
|
|
313
313
|
case 3: {
|
|
314
314
|
return seq.concat(
|
|
315
315
|
values(node[0]),
|
|
316
|
-
|
|
316
|
+
[node[1]],
|
|
317
317
|
values(node[2])
|
|
318
318
|
)
|
|
319
319
|
}
|
|
320
320
|
default: {
|
|
321
321
|
return seq.concat(
|
|
322
322
|
values(node[0]),
|
|
323
|
-
|
|
323
|
+
[node[1]],
|
|
324
324
|
values(node[2]),
|
|
325
|
-
|
|
325
|
+
[node[3]],
|
|
326
326
|
values(node[4])
|
|
327
327
|
)
|
|
328
328
|
}
|
package/btree/test.js
CHANGED
package/function/index.js
CHANGED
|
@@ -4,15 +4,19 @@
|
|
|
4
4
|
* @typedef {(_: I) => O} Func
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Postfix Compose function.
|
|
9
|
+
*
|
|
10
|
+
* @type {<I, X>(g: Func<I, X>) => <O>(f: Func<X, O>) => Func<I, O>}
|
|
11
|
+
*/
|
|
12
|
+
const compose = g => f => x => f(g(x))
|
|
9
13
|
|
|
10
14
|
/** @type {<T>(value: T) => T} */
|
|
11
|
-
const
|
|
15
|
+
const identity = value => value
|
|
12
16
|
|
|
13
17
|
module.exports = {
|
|
14
18
|
/** @readonly */
|
|
15
|
-
|
|
19
|
+
identity,
|
|
16
20
|
/** @readonly */
|
|
17
21
|
compose,
|
|
18
22
|
}
|
package/json/index.js
CHANGED
|
@@ -14,53 +14,50 @@ const { compose } = require('../function')
|
|
|
14
14
|
|
|
15
15
|
/** @typedef {Object|boolean|string|number|null|Array} Json */
|
|
16
16
|
|
|
17
|
-
/** @type {(value: Json) => (path:
|
|
17
|
+
/** @type {(value: Json) => (path: seq.Sequence<string>) => (src: Json|undefined) => Json} */
|
|
18
18
|
const addProperty = value => {
|
|
19
19
|
/** @type {(path: seq.Sequence<string>) => (src: Json|undefined) => Json} */
|
|
20
20
|
const f = path => src => {
|
|
21
21
|
const result = seq.next(path)
|
|
22
22
|
if (result === undefined) { return value }
|
|
23
23
|
const srcObject = (src === undefined || src === null || typeof src !== 'object' || src instanceof Array) ? {} : src
|
|
24
|
-
const
|
|
25
|
-
return { ...srcObject, [
|
|
26
|
-
}
|
|
27
|
-
return
|
|
24
|
+
const { first, tail } = result
|
|
25
|
+
return { ...srcObject, [first]: f(tail)(object.at(first)(srcObject)) }
|
|
26
|
+
}
|
|
27
|
+
return f
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
/** @type {(_: string) => seq.Sequence<string>} */
|
|
31
|
-
const stringSerialize = input =>
|
|
31
|
+
const stringSerialize = input => [JSON.stringify(input)]
|
|
32
32
|
|
|
33
33
|
/** @type {(_: number) => seq.Sequence<string>} */
|
|
34
|
-
const numberSerialize = input =>
|
|
34
|
+
const numberSerialize = input => [JSON.stringify(input)]
|
|
35
35
|
|
|
36
|
-
const nullSerialize =
|
|
36
|
+
const nullSerialize = ['null']
|
|
37
37
|
|
|
38
|
-
const trueSerialize =
|
|
38
|
+
const trueSerialize = ['true']
|
|
39
39
|
|
|
40
|
-
const falseSerialize =
|
|
40
|
+
const falseSerialize = ['false']
|
|
41
41
|
|
|
42
42
|
/** @type {(_: boolean) => seq.Sequence<string>} */
|
|
43
43
|
const boolSerialize = value => value ? trueSerialize : falseSerialize
|
|
44
44
|
|
|
45
|
-
const colon =
|
|
46
|
-
const comma =
|
|
45
|
+
const colon = [':']
|
|
46
|
+
const comma = [',']
|
|
47
47
|
|
|
48
48
|
/** @type {op.Scan<seq.Sequence<string>, seq.Sequence<string>>} */
|
|
49
49
|
const commaValue = a => [seq.concat(comma, a), commaValue]
|
|
50
50
|
|
|
51
|
-
/** @type {
|
|
52
|
-
const
|
|
51
|
+
/** @type {seq.FoldOperator<seq.Sequence<string>>} */
|
|
52
|
+
const joinOp = a => b => seq.concat(a, comma, b)
|
|
53
53
|
|
|
54
|
-
/** @type {seq.
|
|
55
|
-
const join =
|
|
56
|
-
const _0 = seq.scan(joinScan)(input)
|
|
57
|
-
return seq.flat(_0)
|
|
58
|
-
}
|
|
54
|
+
/** @type {(input: seq.Sequence<seq.Sequence<string>>) => seq.Sequence<string>} */
|
|
55
|
+
const join = seq.fold(joinOp)([])
|
|
59
56
|
|
|
60
57
|
/** @type {(open: string) => (close: string) => (input: seq.Sequence<seq.Sequence<string>>) => seq.Sequence<string>} */
|
|
61
58
|
const list = open => close => {
|
|
62
|
-
const seqOpen =
|
|
63
|
-
const seqClose =
|
|
59
|
+
const seqOpen = [open]
|
|
60
|
+
const seqClose = [close]
|
|
64
61
|
return input => seq.concat(seqOpen, join(input), seqClose)
|
|
65
62
|
}
|
|
66
63
|
|
|
@@ -83,15 +80,15 @@ const serialize = sort => {
|
|
|
83
80
|
f(v))
|
|
84
81
|
/** @type {(object: Object) => seq.Sequence<string>} */
|
|
85
82
|
const objectSerialize = input => {
|
|
86
|
-
const entries =
|
|
83
|
+
const entries = Object.entries(input)
|
|
87
84
|
const sortedEntries = sort(entries)
|
|
85
|
+
const _ = seq.toArray(sortedEntries)
|
|
88
86
|
const serializedEntries = seq.map(propertySerialize)(sortedEntries)
|
|
89
87
|
return objectList(serializedEntries)
|
|
90
88
|
}
|
|
91
89
|
/** @type {(input: Array) => seq.Sequence<string>} */
|
|
92
90
|
const arraySerialize = input => {
|
|
93
|
-
const
|
|
94
|
-
const serializedEntries = seq.map(f)(sequence)
|
|
91
|
+
const serializedEntries = seq.map(f)(input)
|
|
95
92
|
return arrayList(serializedEntries)
|
|
96
93
|
}
|
|
97
94
|
/** @type {(value: Json) => seq.Sequence < string >} */
|
|
@@ -118,7 +115,10 @@ const serialize = sort => {
|
|
|
118
115
|
*
|
|
119
116
|
* @type {(mapEntries: MapEntries) => (value: Json) => string}
|
|
120
117
|
*/
|
|
121
|
-
const stringify = sort => value =>
|
|
118
|
+
const stringify = sort => value => {
|
|
119
|
+
const _s = serialize(sort)(value)
|
|
120
|
+
return seq.join('')(_s)
|
|
121
|
+
}
|
|
122
122
|
|
|
123
123
|
/** @type {(value: string) => Json} */
|
|
124
124
|
const parse = value => JSON.parse(value)
|
package/json/test.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
const json = require('.')
|
|
2
2
|
const { sort } = require('../object')
|
|
3
|
-
const {
|
|
3
|
+
const { identity } = require('../function')
|
|
4
4
|
|
|
5
5
|
if (json.addProperty("Hello")([])({}) !== "Hello") { throw 'error' }
|
|
6
6
|
|
|
7
7
|
{
|
|
8
|
-
const
|
|
8
|
+
const r = json.addProperty("Hello")(['a'])({})
|
|
9
|
+
const x = json.stringify(sort)(r)
|
|
9
10
|
if (x !== '{"a":"Hello"}') { throw x }
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
{
|
|
13
|
-
const x = json.stringify(
|
|
14
|
+
const x = json.stringify(identity)(json.addProperty("Hello")(['a'])({}))
|
|
14
15
|
if (x !== '{"a":"Hello"}') { throw x }
|
|
15
16
|
}
|
|
16
17
|
|
|
@@ -20,7 +21,7 @@ if (json.addProperty("Hello")([])({}) !== "Hello") { throw 'error' }
|
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
{
|
|
23
|
-
const x = json.stringify(
|
|
24
|
+
const x = json.stringify(identity)(json.addProperty("Hello")(['a'])({ c: [], b: 12 }))
|
|
24
25
|
if (x !== '{"c":[],"b":12,"a":"Hello"}') { throw x }
|
|
25
26
|
}
|
|
26
27
|
|
|
@@ -34,6 +35,6 @@ if (json.addProperty("Hello")([])({}) !== "Hello") { throw 'error' }
|
|
|
34
35
|
{
|
|
35
36
|
const _0 = { a: { y: [24] }, c: [], b: 12 }
|
|
36
37
|
const _1 = json.addProperty("Hello")(['a', 'x'])(_0)
|
|
37
|
-
const _2 = json.stringify(
|
|
38
|
+
const _2 = json.stringify(identity)(_1)
|
|
38
39
|
if (_2 !== '{"a":{"y":[24],"x":"Hello"},"c":[],"b":12}') { throw _2 }
|
|
39
40
|
}
|
package/map/index.js
CHANGED
|
@@ -56,14 +56,14 @@ const create = root => ({
|
|
|
56
56
|
* @type {{
|
|
57
57
|
* readonly get: (name: string) => undefined
|
|
58
58
|
* readonly set: (name: string) => <T>(value: T) => Map<T>
|
|
59
|
-
* readonly entries:
|
|
59
|
+
* readonly entries: []
|
|
60
60
|
* readonly root: undefined
|
|
61
61
|
* }}
|
|
62
62
|
*/
|
|
63
63
|
const empty = {
|
|
64
64
|
get: () => undefined,
|
|
65
65
|
set: name => value => create([[name, value]]),
|
|
66
|
-
entries:
|
|
66
|
+
entries: [],
|
|
67
67
|
root: undefined
|
|
68
68
|
}
|
|
69
69
|
|
|
@@ -73,7 +73,9 @@ const setOperator = map => ([k, v]) => map.set(k)(v)
|
|
|
73
73
|
/** @type {<T>(entries: seq.Sequence<Entry<T>>) => Map<T>} */
|
|
74
74
|
const fromEntries = entries => {
|
|
75
75
|
/** @typedef {typeof entries extends seq.Sequence<Entry<infer T>> ? T : never} T */
|
|
76
|
-
|
|
76
|
+
/** @type {Map<T>} */
|
|
77
|
+
const init = empty
|
|
78
|
+
return seq.reduce(setOperator)(init)(entries)
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
module.exports = {
|
package/module-manager/index.js
CHANGED
|
@@ -82,15 +82,11 @@ const internal = pack => {
|
|
|
82
82
|
const externalOrInternal = p =>
|
|
83
83
|
p === undefined ? () => undefined : (typeof p === 'function' ? external(p) : internal(p))
|
|
84
84
|
|
|
85
|
-
/** @type {(_: Dependencies) => (
|
|
85
|
+
/** @type {(_: Dependencies) => (path: Path) => Module|undefined} */
|
|
86
86
|
const external = packages => {
|
|
87
87
|
/** @type {(_: readonly [string, Path]) => Module|undefined} */
|
|
88
88
|
const defined = ([first, tail]) => externalOrInternal(packages(first))(tail)
|
|
89
|
-
|
|
90
|
-
const sf = splitFirst
|
|
91
|
-
return compose
|
|
92
|
-
(option.map(defined))
|
|
93
|
-
(sf)
|
|
89
|
+
return path => option.map(defined)(splitFirst(path))
|
|
94
90
|
}
|
|
95
91
|
|
|
96
92
|
/** @type {(_: Location) => (_: string) => Module|undefined} */
|
package/object/index.js
CHANGED
|
@@ -14,9 +14,6 @@ const map = require('../map')
|
|
|
14
14
|
* @typedef {readonly[string, T]} Entry
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
/** @type {<T>(object: Map<T>) => seq.Sequence<Entry<T>>} */
|
|
18
|
-
const entries = object => array.sequence(Object.entries(object))
|
|
19
|
-
|
|
20
17
|
/** @type {(name: string) => <T>(object: Map<T>) => T|undefined} */
|
|
21
18
|
const at = name => object => Object.getOwnPropertyDescriptor(object, name)?.value
|
|
22
19
|
|
|
@@ -24,8 +21,6 @@ const at = name => object => Object.getOwnPropertyDescriptor(object, name)?.valu
|
|
|
24
21
|
const sort = entries => map.fromEntries(entries).entries
|
|
25
22
|
|
|
26
23
|
module.exports = {
|
|
27
|
-
/** @readonly */
|
|
28
|
-
entries,
|
|
29
24
|
/** @readonly */
|
|
30
25
|
at,
|
|
31
26
|
/** @readonly */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "functionalscript",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.218",
|
|
4
4
|
"description": "FunctionalScript is a functional subset of JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
},
|
|
20
20
|
"homepage": "https://github.com/functionalscript/functionalscript#readme",
|
|
21
21
|
"devDependencies": {
|
|
22
|
-
"@types/node": "^16.11.
|
|
22
|
+
"@types/node": "^16.11.11",
|
|
23
23
|
"typescript": "^4.5.2"
|
|
24
24
|
}
|
|
25
25
|
}
|
package/sequence/README.md
CHANGED
|
@@ -2,11 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
Sequence types:
|
|
4
4
|
|
|
5
|
+
- Sequence
|
|
5
6
|
- Array
|
|
6
|
-
- List
|
|
7
7
|
- Iterable
|
|
8
8
|
- AsyncIterable
|
|
9
9
|
|
|
10
|
+
# Sequence Types
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
type Sequence<T> =
|
|
14
|
+
readonly T[] |
|
|
15
|
+
Thunk<T> |
|
|
16
|
+
|
|
17
|
+
type Thunk<T> = () => Node<T>
|
|
18
|
+
|
|
19
|
+
type Node<T> =
|
|
20
|
+
undefined |
|
|
21
|
+
{ readonly first: T, readonly tail: Sequence<T> } |
|
|
22
|
+
readonly[Sequence<T>, Sequence<T>]
|
|
23
|
+
```
|
|
24
|
+
|
|
10
25
|
## Functions
|
|
11
26
|
|
|
12
27
|
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
|
package/sequence/array/index.js
CHANGED
|
@@ -95,21 +95,6 @@ const splitLast = a => {
|
|
|
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
|
-
|
|
113
98
|
module.exports = {
|
|
114
99
|
/** @readonly */
|
|
115
100
|
at,
|
|
@@ -125,8 +110,4 @@ module.exports = {
|
|
|
125
110
|
splitFirst,
|
|
126
111
|
/** @readonly */
|
|
127
112
|
splitLast,
|
|
128
|
-
/** @readonly */
|
|
129
|
-
sequence,
|
|
130
|
-
/** @readonly */
|
|
131
|
-
fromSequence,
|
|
132
113
|
}
|
package/sequence/index.js
CHANGED
|
@@ -1,346 +1,315 @@
|
|
|
1
|
-
const seqOp = require('./operator')
|
|
2
1
|
const { compose } = require('../function')
|
|
2
|
+
const { logicalNot, strictEqual, addition } = require('../function/operator')
|
|
3
3
|
const op = require('../function/operator')
|
|
4
|
-
const { logicalNot, strictEqual } = require('../function/operator')
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* @template T
|
|
8
|
-
* @typedef {
|
|
7
|
+
* @typedef { readonly T[] | Thunk<T> } Sequence<T>
|
|
9
8
|
*/
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* @template T
|
|
13
|
-
* @typedef {
|
|
12
|
+
* @typedef { () => Node<T> } Thunk
|
|
14
13
|
*/
|
|
15
14
|
|
|
16
15
|
/**
|
|
17
|
-
* Use `next` function to get `first` and `tail` of the list.
|
|
18
|
-
*
|
|
19
|
-
* Please note that the sequence also contains `Concat<T>. We need this as
|
|
20
|
-
* a workaround because modern JavaScript implementations don't support
|
|
21
|
-
* ES6 TCO (Tail Call Optimization). Without this wotkaround we may have
|
|
22
|
-
* a stack overflow if a list contains a lot of concateneted lists.
|
|
23
|
-
*
|
|
24
16
|
* @template T
|
|
25
|
-
* @typedef {
|
|
17
|
+
* @typedef { Result<T> | Concat<T> } Node<T>
|
|
26
18
|
*/
|
|
27
19
|
|
|
28
20
|
/**
|
|
29
21
|
* @template T
|
|
30
|
-
* @typedef {
|
|
22
|
+
* @typedef { readonly[Sequence<T>, Sequence<T>] } Concat<T>
|
|
31
23
|
*/
|
|
32
24
|
|
|
33
25
|
/**
|
|
34
26
|
* @template T
|
|
35
|
-
* @typedef {readonly
|
|
27
|
+
* @typedef { undefined | { readonly first: T, readonly tail: Sequence<T> } } Result
|
|
36
28
|
*/
|
|
37
29
|
|
|
38
30
|
const empty = () => undefined
|
|
39
31
|
|
|
40
|
-
/** @type {<
|
|
41
|
-
const
|
|
32
|
+
/** @type {<T>(array: readonly T[]) => Result<T>} */
|
|
33
|
+
const fromArray = array => {
|
|
34
|
+
/** @typedef {typeof array extends readonly(infer T)[] ? T : never} T */
|
|
35
|
+
/** @type {(index: number) => Result<T>} */
|
|
36
|
+
const at = index => {
|
|
37
|
+
if (array.length <= index) { return undefined }
|
|
38
|
+
return { first: array[index], tail: () => at(index + 1) }
|
|
39
|
+
}
|
|
40
|
+
return at(0)
|
|
41
|
+
}
|
|
42
42
|
|
|
43
|
-
/** @type {<T>(
|
|
44
|
-
const
|
|
45
|
-
|
|
43
|
+
/** @type {<T>(sequence: Sequence<T>) => Node<T>} */
|
|
44
|
+
const node = sequence => sequence instanceof Array ? fromArray(sequence) : sequence()
|
|
45
|
+
|
|
46
|
+
/** @type {<T>(concat: Concat<T>) => Sequence<T>} */
|
|
47
|
+
const concatNext = ([a, b]) => {
|
|
48
|
+
const result = node(a)
|
|
49
|
+
if (result === undefined) {
|
|
50
|
+
return b
|
|
51
|
+
} else if (result instanceof Array) {
|
|
52
|
+
const [aa, ab] = result
|
|
53
|
+
return () => [aa, () => [ab, b]]
|
|
54
|
+
} else {
|
|
55
|
+
const { first, tail } = result
|
|
56
|
+
return () => ({ first, tail: () => [tail, b] })
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** @type {<T>(sequence: Sequence<T>) => Result<T>} */
|
|
61
|
+
const next = sequence => {
|
|
62
|
+
let i = sequence
|
|
46
63
|
while (true) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
64
|
+
const n = node(i)
|
|
65
|
+
if (!(n instanceof Array)) { return n }
|
|
66
|
+
i = concatNext(n)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** @type {<T>(sequence: Sequence<T>) => Iterable<T>} */
|
|
71
|
+
const iterable = sequence => ({
|
|
72
|
+
*[Symbol.iterator]() {
|
|
73
|
+
let i = sequence
|
|
74
|
+
while (true) {
|
|
75
|
+
if (i instanceof Array) { return yield *i }
|
|
76
|
+
const n = node(i)
|
|
77
|
+
if (n === undefined) { return }
|
|
78
|
+
if (n instanceof Array) {
|
|
79
|
+
i = concatNext(n)
|
|
80
|
+
} else {
|
|
81
|
+
const { first, tail } = n
|
|
82
|
+
yield first
|
|
83
|
+
i = tail
|
|
53
84
|
}
|
|
54
|
-
i = b
|
|
55
|
-
} else {
|
|
56
|
-
i = norm(a)(b)
|
|
57
85
|
}
|
|
58
86
|
}
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
/** @type {<T>(sequence: Sequence<T>) => readonly T[]} */
|
|
90
|
+
const toArray = sequence => {
|
|
91
|
+
if (sequence instanceof Array) { return sequence }
|
|
92
|
+
return Array.from(iterable(sequence))
|
|
59
93
|
}
|
|
60
94
|
|
|
61
|
-
/** @type {<T>(
|
|
62
|
-
const
|
|
63
|
-
const
|
|
64
|
-
if (
|
|
65
|
-
|
|
95
|
+
/** @type {<T>(sequence: Sequence<Sequence<T>>) => Thunk<T>} */
|
|
96
|
+
const flat = sequence => () => {
|
|
97
|
+
const n = next(sequence)
|
|
98
|
+
if (n === undefined) { return undefined }
|
|
99
|
+
const { first, tail } = n
|
|
100
|
+
return [first, flat(tail)]
|
|
66
101
|
}
|
|
67
102
|
|
|
68
|
-
/**
|
|
69
|
-
|
|
70
|
-
* @template R
|
|
71
|
-
* @typedef {(list: Sequence<T>) => Sequence<R>} SequenceMap
|
|
72
|
-
*/
|
|
103
|
+
/** @type {<T>(...array: readonly Sequence<T>[]) => Thunk<T>} */
|
|
104
|
+
const concat = (...array) => flat(array)
|
|
73
105
|
|
|
74
|
-
/**
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
106
|
+
/** @type {<I, O>(f: (value: I) => O) => (input: Sequence<I>) => Thunk<O>} */
|
|
107
|
+
const map = f => sequence => () => {
|
|
108
|
+
const n = next(sequence)
|
|
109
|
+
if (n === undefined) { return undefined }
|
|
110
|
+
const { first, tail } = n
|
|
111
|
+
return { first: f(first), tail: map(f)(tail) }
|
|
112
|
+
}
|
|
79
113
|
|
|
80
|
-
/**
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
while (i !== 0) {
|
|
91
|
-
i = i - 1
|
|
92
|
-
/** @type {FirstAndTail<T>} */
|
|
93
|
-
const listResult = [array[i], result]
|
|
94
|
-
result = () => listResult
|
|
95
|
-
}
|
|
96
|
-
return result
|
|
114
|
+
/** @type {<I, O>(f: (value: I) => Sequence<O>) => (input: Sequence<I>) => Thunk<O>} */
|
|
115
|
+
const flatMap = f => sequence => flat(map(f)(sequence))
|
|
116
|
+
|
|
117
|
+
/** @type {<T>(f: (value: T) => boolean) => (input: Sequence<T>) => Thunk<T>} */
|
|
118
|
+
const filter = f => sequence => () => {
|
|
119
|
+
const n = next(sequence)
|
|
120
|
+
if (n === undefined) { return undefined }
|
|
121
|
+
const { first, tail } = n
|
|
122
|
+
const fTail = filter(f)(tail)
|
|
123
|
+
return f(first) ? { first, tail: fTail } : fTail()
|
|
97
124
|
}
|
|
98
125
|
|
|
99
|
-
/** @type {<
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
if (
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
result = [array[i], result]
|
|
108
|
-
}
|
|
109
|
-
return result
|
|
126
|
+
/** @type {<I, O>(f: (value: I) => O|undefined) => (input: Sequence<I>) => Thunk<O>} */
|
|
127
|
+
const filterMap = f => sequence => () => {
|
|
128
|
+
const n = next(sequence)
|
|
129
|
+
if (n === undefined) { return undefined }
|
|
130
|
+
const { first, tail } = n
|
|
131
|
+
const fFirst = f(first)
|
|
132
|
+
const fTail = filterMap(f)(tail)
|
|
133
|
+
return fFirst === undefined ? fTail() : { first: fFirst, tail: fTail }
|
|
110
134
|
}
|
|
111
135
|
|
|
112
|
-
/** @type {(
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
return f(0)
|
|
136
|
+
/** @type {<T>(f: (value: T) => boolean) => (input: Sequence<T>) => Thunk<T>} */
|
|
137
|
+
const takeWhile = f => input => () => {
|
|
138
|
+
const result = next(input)
|
|
139
|
+
if (result === undefined) { return undefined }
|
|
140
|
+
const { first, tail } = result
|
|
141
|
+
if (!f(first)) { return undefined }
|
|
142
|
+
return { first, tail: takeWhile(f)(result.tail) }
|
|
120
143
|
}
|
|
121
144
|
|
|
122
|
-
/** @type {<T
|
|
123
|
-
const
|
|
145
|
+
/** @type {<T>(f: (value: T) => boolean) => (input: Sequence<T>) => Thunk<T>} */
|
|
146
|
+
const dropWhile = f => input => () => {
|
|
124
147
|
let i = input
|
|
125
|
-
while (true) {
|
|
148
|
+
while (true) {
|
|
126
149
|
const result = next(i)
|
|
127
150
|
if (result === undefined) { return undefined }
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
if (firstResult !== undefined) {
|
|
131
|
-
return norm(firstResult)(flatMap(f)(tail))
|
|
132
|
-
}
|
|
151
|
+
const { first, tail } = result
|
|
152
|
+
if (!f(first)) return result
|
|
133
153
|
i = tail
|
|
134
154
|
}
|
|
135
155
|
}
|
|
136
156
|
|
|
137
|
-
/** @type {<T>(
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
/** @type {<T, R>(f: (value: T) => R) => SequenceMap<T, R>} */
|
|
141
|
-
const map = f => flatMap(i => list(f(i)))
|
|
142
|
-
|
|
143
|
-
/** @type {<T>(f: (value: T) => boolean) => SequenceMap<T, T>} */
|
|
144
|
-
const filter = f => flatMap(i => f(i) ? list(i) : empty)
|
|
145
|
-
|
|
146
|
-
/** @type {<T, R>(f: (value: T) => R|undefined) => (value: T) => Sequence<R>} */
|
|
147
|
-
const filterMapFunc = f => i => {
|
|
148
|
-
const result = f(i)
|
|
149
|
-
if (result === undefined) { return empty }
|
|
150
|
-
return list(result)
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/** @type {<T, R>(f: (value: T) => R|undefined) => SequenceMap<T, R>} */
|
|
154
|
-
const filterMap = f => flatMap(filterMapFunc(f))
|
|
155
|
-
|
|
156
|
-
/** @type {<T, R>(s: seqOp.Scan<T, R>) => SequenceMap<T, R>} */
|
|
157
|
-
const scan = s => input => () => {
|
|
157
|
+
/** @type {<D>(def: D) => <T>(input: Sequence<T>) => D|T} */
|
|
158
|
+
const first = def => input => {
|
|
158
159
|
const result = next(input)
|
|
159
|
-
if (result === undefined) {
|
|
160
|
-
|
|
161
|
-
}
|
|
162
|
-
const [first, tail] = result
|
|
163
|
-
const [newFirst, newS] = s(first)
|
|
164
|
-
return [newFirst, scan(newS)(tail)]
|
|
160
|
+
if (result === undefined) { return def }
|
|
161
|
+
return result.first
|
|
165
162
|
}
|
|
166
163
|
|
|
167
|
-
/** @type {<T
|
|
168
|
-
const exclusiveScan = ([first, s]) => input => () => [first, scan(s)(input)]
|
|
169
|
-
|
|
170
|
-
/** @type {<T>(def: T) => (input: Sequence<T>) => T} */
|
|
164
|
+
/** @type {<D>(def: D) => <T>(input: Sequence<T>) => D|T} */
|
|
171
165
|
const last = def => input => {
|
|
166
|
+
/** @typedef {typeof input extends Sequence<infer T> ? T : never} T */
|
|
167
|
+
/** @type {(typeof def)|T} */
|
|
172
168
|
let r = def
|
|
173
|
-
let i = input
|
|
169
|
+
let i = input
|
|
174
170
|
while (true) {
|
|
175
171
|
const result = next(i)
|
|
176
172
|
if (result === undefined) {
|
|
177
173
|
return r
|
|
178
174
|
}
|
|
179
|
-
r = result
|
|
180
|
-
i = result
|
|
175
|
+
r = result.first
|
|
176
|
+
i = result.tail
|
|
181
177
|
}
|
|
182
178
|
}
|
|
183
179
|
|
|
184
|
-
/** @type {<
|
|
185
|
-
const
|
|
180
|
+
/** @type {<D>(def: D) => <T>(f: (value: T) => boolean) => (sequence: Sequence<T>) => D|T} */
|
|
181
|
+
const find = def => f => input => first(def)(filter(f)(input))
|
|
186
182
|
|
|
187
|
-
/** @type {<T
|
|
188
|
-
const
|
|
183
|
+
/** @type {<T>(f: (value: T) => boolean) => (sequence: Sequence<T>) => boolean} */
|
|
184
|
+
const some = f => input => find(false)(x => x)(map(f)(input))
|
|
189
185
|
|
|
190
|
-
|
|
186
|
+
/** @type {<T>(f: (value: T) => boolean) => (sequence: Sequence<T>) => boolean} */
|
|
187
|
+
const every = f => input => !some(compose(f)(logicalNot))(input)
|
|
191
188
|
|
|
192
|
-
|
|
189
|
+
/** @type {<T>(value: T) => (sequence: Sequence<T>) => boolean} */
|
|
190
|
+
const includes = value => some(strictEqual(value))
|
|
191
|
+
|
|
192
|
+
/** @type {(count: number) => Thunk<number>} */
|
|
193
|
+
const countdown = count => () => {
|
|
194
|
+
if (count <= 0) { return undefined }
|
|
195
|
+
const first = count - 1
|
|
196
|
+
return { first, tail: countdown(first) }
|
|
197
|
+
}
|
|
193
198
|
|
|
194
|
-
|
|
199
|
+
/**
|
|
200
|
+
* @template T,A
|
|
201
|
+
* @typedef {(value: T) => ScanState<T, A>} ScanFunc
|
|
202
|
+
*/
|
|
195
203
|
|
|
196
|
-
/**
|
|
197
|
-
|
|
204
|
+
/**
|
|
205
|
+
* @template T,A
|
|
206
|
+
* @typedef {readonly[A, ScanFunc<T, A>]} ScanState
|
|
207
|
+
*/
|
|
198
208
|
|
|
199
|
-
/** @type {<T>(
|
|
200
|
-
const
|
|
209
|
+
/** @type {<T,A>(operator: ScanFunc<T, A>) => (input: Sequence<T>) => Thunk<A>} */
|
|
210
|
+
const scan = operator => input => () => {
|
|
201
211
|
const result = next(input)
|
|
202
|
-
if (result === undefined
|
|
203
|
-
|
|
212
|
+
if (result === undefined) { return undefined }
|
|
213
|
+
const { first, tail } = result
|
|
214
|
+
const r = operator(first)
|
|
215
|
+
return { first: r[0], tail: scan(r[1])(tail) }
|
|
204
216
|
}
|
|
205
217
|
|
|
206
|
-
/** @type {(
|
|
207
|
-
const
|
|
208
|
-
let iN = n
|
|
209
|
-
let iInput = input
|
|
210
|
-
while (true) {
|
|
211
|
-
const result = next(iInput)
|
|
212
|
-
if (iN <= 0 || result === undefined) { return result }
|
|
213
|
-
iN = iN - 1
|
|
214
|
-
iInput = result[1]
|
|
215
|
-
}
|
|
216
|
-
}
|
|
218
|
+
/** @type {<T,A>(operator: ScanFunc<T, A>) => <D>(def: D)=> (input: Sequence<T>) => D|A} */
|
|
219
|
+
const scanReduce = operator => def => input => last(def)(scan(operator)(input))
|
|
217
220
|
|
|
218
|
-
/**
|
|
219
|
-
|
|
221
|
+
/**
|
|
222
|
+
* @template T,A
|
|
223
|
+
* @typedef {(prior: A) => (value: T) => A} ReduceOperator
|
|
224
|
+
*/
|
|
220
225
|
|
|
221
|
-
/** @type {<T>(
|
|
222
|
-
const
|
|
226
|
+
/** @type {<T,A>(operator: ReduceOperator<T, A>) => (init: A) => ScanState<T, A>} */
|
|
227
|
+
const scanState = operator => init => [init, scanFunc(operator)(init)]
|
|
223
228
|
|
|
224
|
-
/** @type {<T>(
|
|
225
|
-
const
|
|
229
|
+
/** @type {<T,A>(operator: ReduceOperator<T, A>) => (init: A) => ScanFunc<T, A>} */
|
|
230
|
+
const scanFunc = operator => init => value => {
|
|
231
|
+
const result = operator(init)(value)
|
|
232
|
+
return scanState(operator)(result)
|
|
233
|
+
}
|
|
226
234
|
|
|
227
|
-
/** @type {<T>(
|
|
228
|
-
const
|
|
235
|
+
/** @type {<T,A>(operator: ReduceOperator<T, A>) => (init: A) => (input: Sequence<T>) => A} */
|
|
236
|
+
const reduce = operator => init => scanReduce(scanFunc(operator)(init))(init)
|
|
229
237
|
|
|
230
|
-
/**
|
|
231
|
-
|
|
238
|
+
/**
|
|
239
|
+
* @template T
|
|
240
|
+
* @typedef {ReduceOperator<T, T>} FoldOperator
|
|
241
|
+
*/
|
|
232
242
|
|
|
233
|
-
/** @type {<T>(
|
|
234
|
-
const
|
|
235
|
-
*[Symbol.iterator]() {
|
|
236
|
-
let i = list
|
|
237
|
-
while (true) {
|
|
238
|
-
const result = next(i)
|
|
239
|
-
if (result === undefined) { return }
|
|
240
|
-
yield result[0]
|
|
241
|
-
i = result[1]
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
})
|
|
243
|
+
/** @type {<T>(operator: FoldOperator<T>) => <D>(def: D) => (input: Sequence<T>) => D|T} */
|
|
244
|
+
const fold = operator => def => scanReduce(scanState(operator))(def)
|
|
245
245
|
|
|
246
|
-
|
|
247
|
-
const asyncIterable = list => ({
|
|
248
|
-
async *[Symbol.asyncIterator]() {
|
|
249
|
-
let i = list
|
|
250
|
-
while (true) {
|
|
251
|
-
const result = next(i)
|
|
252
|
-
if (result === undefined) { return }
|
|
253
|
-
yield result[0]
|
|
254
|
-
i = result[1]
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
})
|
|
246
|
+
const sum = fold(addition)(0)
|
|
258
247
|
|
|
259
|
-
/** @type {
|
|
260
|
-
const
|
|
261
|
-
const resultA = next(a)
|
|
262
|
-
if (resultA === undefined) { return undefined }
|
|
263
|
-
const resultB = next(b)
|
|
264
|
-
if (resultB === undefined) { return undefined }
|
|
265
|
-
return [[resultA[0], resultB[0]], zip(resultA[1])(resultB[1])]
|
|
266
|
-
}
|
|
248
|
+
/** @type {(separator: string) => (input: Sequence<string>) => string} */
|
|
249
|
+
const join = separator => fold(op.join(separator))('')
|
|
267
250
|
|
|
268
|
-
/**
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
iResult = () => [result[0], old]
|
|
279
|
-
iSource = result[1]
|
|
280
|
-
}
|
|
281
|
-
}
|
|
251
|
+
/**
|
|
252
|
+
* @template T
|
|
253
|
+
* @typedef {readonly[number, T]} Entry
|
|
254
|
+
*/
|
|
255
|
+
|
|
256
|
+
/** @type {(index: number) => <T>(value: T) => ScanState<T, Entry<T>>} */
|
|
257
|
+
const entryOp = index => value => [[index, value], entryOp(index + 1)]
|
|
258
|
+
|
|
259
|
+
/** @type {<T>(input: Sequence<T>) => Thunk<Entry<T>>} */
|
|
260
|
+
const entries = scan(entryOp(0))
|
|
282
261
|
|
|
283
262
|
module.exports = {
|
|
263
|
+
/** @readonly */
|
|
264
|
+
empty,
|
|
265
|
+
/** @readonly */
|
|
266
|
+
iterable,
|
|
284
267
|
/** @readonly */
|
|
285
268
|
next,
|
|
286
269
|
/** @readonly */
|
|
287
|
-
|
|
270
|
+
toArray,
|
|
288
271
|
/** @readonly */
|
|
289
|
-
|
|
272
|
+
flat,
|
|
290
273
|
/** @readonly */
|
|
291
|
-
|
|
274
|
+
last,
|
|
292
275
|
/** @readonly */
|
|
293
276
|
concat,
|
|
294
277
|
/** @readonly */
|
|
295
|
-
generate,
|
|
296
|
-
/** @readonly */
|
|
297
278
|
first,
|
|
298
279
|
/** @readonly */
|
|
299
|
-
|
|
300
|
-
/** @readonly */
|
|
301
|
-
asyncIterable,
|
|
280
|
+
map,
|
|
302
281
|
/** @readonly */
|
|
303
282
|
flatMap,
|
|
304
283
|
/** @readonly */
|
|
305
|
-
flat,
|
|
306
|
-
/** @readonly */
|
|
307
|
-
map,
|
|
308
|
-
/** @readonly */
|
|
309
284
|
filter,
|
|
310
285
|
/** @readonly */
|
|
311
|
-
|
|
312
|
-
/** @readonly */
|
|
313
|
-
scan,
|
|
314
|
-
/** @readonly */
|
|
315
|
-
exclusiveScan,
|
|
316
|
-
/** @readonly */
|
|
317
|
-
last,
|
|
286
|
+
find,
|
|
318
287
|
/** @readonly */
|
|
319
|
-
|
|
288
|
+
some,
|
|
320
289
|
/** @readonly */
|
|
321
|
-
|
|
290
|
+
every,
|
|
322
291
|
/** @readonly */
|
|
323
|
-
|
|
292
|
+
includes,
|
|
324
293
|
/** @readonly */
|
|
325
|
-
|
|
294
|
+
takeWhile,
|
|
326
295
|
/** @readonly */
|
|
327
|
-
|
|
296
|
+
dropWhile,
|
|
328
297
|
/** @readonly */
|
|
329
|
-
|
|
298
|
+
scanFunc,
|
|
330
299
|
/** @readonly */
|
|
331
|
-
|
|
300
|
+
scanState,
|
|
332
301
|
/** @readonly */
|
|
333
|
-
|
|
302
|
+
scan,
|
|
334
303
|
/** @readonly */
|
|
335
|
-
|
|
304
|
+
reduce,
|
|
336
305
|
/** @readonly */
|
|
337
|
-
|
|
306
|
+
fold,
|
|
338
307
|
/** @readonly */
|
|
339
|
-
|
|
308
|
+
sum,
|
|
340
309
|
/** @readonly */
|
|
341
|
-
|
|
310
|
+
join,
|
|
342
311
|
/** @readonly */
|
|
343
|
-
|
|
312
|
+
entries,
|
|
344
313
|
/** @readonly */
|
|
345
|
-
|
|
346
|
-
}
|
|
314
|
+
countdown,
|
|
315
|
+
}
|
|
@@ -39,7 +39,7 @@ const sum = reduce(seq.sum)
|
|
|
39
39
|
|
|
40
40
|
const length = reduce(seq.length)
|
|
41
41
|
|
|
42
|
-
const join = compose(
|
|
42
|
+
const join = compose(seq.join)(reduce)
|
|
43
43
|
|
|
44
44
|
/** @type {<T, R>(f: (value: T) => Iterable<R>) => (c: Iterable<T>) => Iterable<R>} */
|
|
45
45
|
const flatMap = f => c => ({
|
|
@@ -34,8 +34,8 @@ const { compose } = require('../../function')
|
|
|
34
34
|
const file = _ => 'x'
|
|
35
35
|
/** @type {(_: string) => string|undefined} */
|
|
36
36
|
const x = p => compose
|
|
37
|
-
(i.
|
|
38
|
-
(i.
|
|
37
|
+
(i.map(x => file(x())))
|
|
38
|
+
(i.find(x => x !== undefined))
|
|
39
39
|
([() => p, () => `${p}.js`, () => `${p}/index.js`])
|
|
40
40
|
if (x('index.js') !== 'x') { throw 'error' }
|
|
41
41
|
}
|
|
@@ -35,7 +35,7 @@ const scan = operator => {
|
|
|
35
35
|
return [result, f(result)]
|
|
36
36
|
}
|
|
37
37
|
return f
|
|
38
|
-
}
|
|
38
|
+
}
|
|
39
39
|
|
|
40
40
|
/** @type {<R, T>(operator: op.ReduceOperator<R, T>) => (first: R) => ExclusiveScan<T, R>} */
|
|
41
41
|
const exclusiveScan = operator => first => [first, scan(operator)(first)]
|
package/sequence/test.js
CHANGED
|
@@ -1,74 +1,142 @@
|
|
|
1
|
-
const
|
|
2
|
-
const { sum } = require('./operator')
|
|
3
|
-
const array = require('./array')
|
|
1
|
+
const _ = require('.')
|
|
4
2
|
const json = require('../json')
|
|
5
|
-
const {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
3
|
+
const { sort } = require('../object')
|
|
4
|
+
const { addition } = require('../function/operator')
|
|
5
|
+
|
|
6
|
+
/** @type {(sequence: _.Sequence<json.Json>) => string} */
|
|
7
|
+
const stringify = sequence => json.stringify(sort)(_.toArray(sequence))
|
|
8
|
+
|
|
9
|
+
{
|
|
10
|
+
const s = stringify([1, 2, 3])
|
|
11
|
+
if (s !== '[1,2,3]') { throw s }
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
{
|
|
15
|
+
const result = stringify(_.countdown(10))
|
|
16
|
+
if (result !== '[9,8,7,6,5,4,3,2,1,0]') { throw result }
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
{
|
|
20
|
+
const result = stringify(_.concat([1, 2, 3], [4, 5], [6], [], [7, 8, 9]))
|
|
21
|
+
if (result !== '[1,2,3,4,5,6,7,8,9]') { throw result }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
{
|
|
25
|
+
const result = _.concat([1], [2])
|
|
26
|
+
const x = _.next(result)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
{
|
|
30
|
+
const result = stringify(_.flatMap(x => [x, x * 2, x * 3])([0, 1, 2, 3]))
|
|
31
|
+
if (result !== '[0,0,0,1,2,3,2,4,6,3,6,9]') { throw result }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
{
|
|
35
|
+
const result = stringify(_.takeWhile(x => x < 6)([1, 2, 3, 4, 5, 6, 7, 8, 9]))
|
|
36
|
+
if (result !== '[1,2,3,4,5]') { throw result }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
{
|
|
40
|
+
const result = _.find(undefined)(x => x % 2 === 0)([1, 2, 3, 4])
|
|
41
|
+
if (result !== 2) { throw result }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
{
|
|
45
|
+
const result = stringify(_.takeWhile(x => x < 10)([1, 2, 3, 4, 5, 10, 11]))
|
|
46
|
+
if (result !== '[1,2,3,4,5]') { throw result }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
{
|
|
50
|
+
const result = stringify(_.dropWhile(x => x < 10)([1, 2, 3, 4, 5, 10, 11]))
|
|
51
|
+
if (result !== '[10,11]') { throw result }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
{
|
|
55
|
+
const op = _.scanState(addition)
|
|
56
|
+
const result = stringify(_.scan(op)([2, 3, 4, 5]))
|
|
57
|
+
if (result !== '[2,5,9,14]') { throw result }
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
{
|
|
61
|
+
const result = _.sum([2, 3, 4, 5])
|
|
62
|
+
if (result !== 14) { throw result }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
{
|
|
66
|
+
const result = _.fold(addition)(undefined)([2, 3, 4, 5])
|
|
67
|
+
if (result !== 14) { throw result }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
{
|
|
71
|
+
const result = _.fold(addition)(undefined)([])
|
|
72
|
+
if (result !== undefined) { throw result }
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
{
|
|
76
|
+
const result = _.join('/')([])
|
|
77
|
+
if (result !== '') { throw result }
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
{
|
|
81
|
+
const result = _.join('/')([''])
|
|
82
|
+
if (result !== '') { throw result }
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
{
|
|
86
|
+
const result = stringify(_.entries([]))
|
|
87
|
+
if (result !== '[]') { throw result }
|
|
16
88
|
}
|
|
17
89
|
|
|
18
90
|
{
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (seq.every(x => x < 20)(big) !== false) { throw 'x' }
|
|
27
|
-
if (seq.some(x => x > 100)(big) !== false) { throw 'x' }
|
|
28
|
-
if (seq.some(x => x > 50)(big) !== true) { throw 'x' }
|
|
29
|
-
if (seq.first(seq.drop(16)(big)) !== 42) { throw 'drop'}
|
|
91
|
+
const result = stringify(_.entries(['hello', 'world']))
|
|
92
|
+
if (result !== '[[0,"hello"],[1,"world"]]') { throw result }
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// stress tests
|
|
96
|
+
|
|
97
|
+
const stress = () => {
|
|
30
98
|
{
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const r = seq.next(x)
|
|
38
|
-
// print(x)
|
|
99
|
+
// 200_000_000 is too much
|
|
100
|
+
const n = 100_000_000
|
|
101
|
+
const result = _.toArray(_.countdown(n))
|
|
102
|
+
if (result.length !== n) { throw result.length }
|
|
103
|
+
const first = _.first(undefined)(result)
|
|
104
|
+
if (first !== n - 1) { throw first }
|
|
39
105
|
}
|
|
106
|
+
|
|
40
107
|
{
|
|
41
|
-
|
|
42
|
-
let
|
|
43
|
-
|
|
44
|
-
|
|
108
|
+
/** @type {_.Sequence<number>} */
|
|
109
|
+
let sequence = []
|
|
110
|
+
// 2_000_000 is too much
|
|
111
|
+
for (let i = 0; i < 1_000_000; ++i) {
|
|
112
|
+
sequence = _.concat(sequence, [i])
|
|
113
|
+
}
|
|
114
|
+
const r = _.toArray(sequence)
|
|
45
115
|
}
|
|
116
|
+
|
|
46
117
|
{
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
118
|
+
/** @type {_.Sequence<number>} */
|
|
119
|
+
let sequence = []
|
|
120
|
+
// 5_000_000 is too much
|
|
121
|
+
for (let i = 0; i < 2_000_000; ++i) {
|
|
122
|
+
sequence = _.concat(sequence, [i])
|
|
50
123
|
}
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
124
|
+
const a = _.next(sequence)
|
|
125
|
+
}
|
|
126
|
+
|
|
54
127
|
{
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
128
|
+
/** @type {_.Sequence<number>} */
|
|
129
|
+
let sequence = []
|
|
130
|
+
// 10_000_000 is too much
|
|
131
|
+
for (let i = 0; i < 5_000_000; ++i) {
|
|
132
|
+
sequence = _.concat([i], sequence)
|
|
58
133
|
}
|
|
59
|
-
const
|
|
60
|
-
// print(x)
|
|
134
|
+
const a = _.next(sequence)
|
|
61
135
|
}
|
|
62
136
|
}
|
|
63
137
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
138
|
+
//stress()
|
|
139
|
+
|
|
140
|
+
module.exports = {
|
|
68
141
|
|
|
69
|
-
{
|
|
70
|
-
const r = seq.reverse(seq.list(1, 2, 3, 4))
|
|
71
|
-
const s = array.fromSequence(r)
|
|
72
|
-
const j = json.stringify(id)(s)
|
|
73
|
-
if (j !== '[4,3,2,1]') { throw j }
|
|
74
142
|
}
|
package/test.js
CHANGED
|
@@ -82,14 +82,14 @@ const assert_if = c => { if (c) { throw 'assert_if' } }
|
|
|
82
82
|
constructor: undefined
|
|
83
83
|
}
|
|
84
84
|
const c = o['constructor']
|
|
85
|
-
console.log(c)
|
|
85
|
+
//console.log(c)
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
{
|
|
89
89
|
/** @type {any} */
|
|
90
90
|
const b = '42'
|
|
91
91
|
const r = Number(b)
|
|
92
|
-
console.log(r)
|
|
92
|
+
//console.log(r)
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
{
|
|
@@ -106,7 +106,7 @@ const assert_if = c => { if (c) { throw 'assert_if' } }
|
|
|
106
106
|
//const c = o['propertyIsEnumerable']
|
|
107
107
|
//const c = o['toString']
|
|
108
108
|
const c = o['valueOf']
|
|
109
|
-
console.log(c)
|
|
109
|
+
//console.log(c)
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
{
|