functionalscript 0.0.222 → 0.0.224
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/package.json +1 -1
- package/sequence/index.js +24 -26
- package/sequence/test.js +23 -0
package/package.json
CHANGED
package/sequence/index.js
CHANGED
|
@@ -19,7 +19,7 @@ const op = require('../function/operator')
|
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* @template T
|
|
22
|
-
* @typedef { readonly[Sequence<T>, Sequence<T>]
|
|
22
|
+
* @typedef { readonly[Sequence<T>, Sequence<T>]} Concat<T>
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
25
|
/**
|
|
@@ -34,6 +34,9 @@ const op = require('../function/operator')
|
|
|
34
34
|
|
|
35
35
|
const empty = () => undefined
|
|
36
36
|
|
|
37
|
+
/** @type {<T>(sequence: Sequence<T>) => Node<T>} */
|
|
38
|
+
const nodeOne = sequence => [empty, sequence]
|
|
39
|
+
|
|
37
40
|
/** @type {<T>(array: readonly T[]) => Result<T>} */
|
|
38
41
|
const fromArray = array => {
|
|
39
42
|
/** @typedef {typeof array extends readonly(infer T)[] ? T : never} T */
|
|
@@ -48,27 +51,23 @@ const fromArray = array => {
|
|
|
48
51
|
/** @type {<T>(sequence: Sequence<T>) => Node<T>} */
|
|
49
52
|
const node = sequence => sequence instanceof Array ? fromArray(sequence) : sequence()
|
|
50
53
|
|
|
51
|
-
/** @type {<T>(concat: Concat<T>) => Sequence<T>} */
|
|
52
|
-
const concatNext = ([a, b]) => {
|
|
53
|
-
const result = node(a)
|
|
54
|
-
if (result === undefined) {
|
|
55
|
-
return b
|
|
56
|
-
} else if (result instanceof Array) {
|
|
57
|
-
const [aa, ab] = result
|
|
58
|
-
return () => [aa, () => [ab, b]]
|
|
59
|
-
} else {
|
|
60
|
-
const { first, tail } = result
|
|
61
|
-
return () => ({ first, tail: () => [tail, b] })
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
54
|
/** @type {<T>(sequence: Sequence<T>) => Result<T>} */
|
|
66
55
|
const next = sequence => {
|
|
67
56
|
let i = sequence
|
|
68
57
|
while (true) {
|
|
69
58
|
const n = node(i)
|
|
70
59
|
if (!(n instanceof Array)) { return n }
|
|
71
|
-
|
|
60
|
+
const [a, b] = n
|
|
61
|
+
const result = node(a)
|
|
62
|
+
if (result === undefined) {
|
|
63
|
+
i = b
|
|
64
|
+
} else if (result instanceof Array) {
|
|
65
|
+
const [aa, ab] = result
|
|
66
|
+
i = () => [aa, () => [ab, b]]
|
|
67
|
+
} else {
|
|
68
|
+
const { first, tail } = result
|
|
69
|
+
return { first, tail: () => [tail, b] }
|
|
70
|
+
}
|
|
72
71
|
}
|
|
73
72
|
}
|
|
74
73
|
|
|
@@ -121,7 +120,7 @@ const flatMap = f => compose(map(f))(flat)
|
|
|
121
120
|
/** @type {<T>(f: (value: T) => boolean) => (result: ResultOne<T>) => Node<T>} */
|
|
122
121
|
const filterFn = f => ({ first, tail }) => {
|
|
123
122
|
const fTail = filter(f)(tail)
|
|
124
|
-
return f(first) ? { first, tail: fTail } : fTail
|
|
123
|
+
return f(first) ? { first, tail: fTail } : nodeOne(fTail)
|
|
125
124
|
}
|
|
126
125
|
|
|
127
126
|
/** @type {<T>(f: (value: T) => boolean) => (input: Sequence<T>) => Thunk<T>} */
|
|
@@ -131,7 +130,7 @@ const filter = f => nextMap(filterFn(f))
|
|
|
131
130
|
const filterMapFn = f => ({first, tail}) => {
|
|
132
131
|
const fFirst = f(first)
|
|
133
132
|
const fTail = filterMap(f)(tail)
|
|
134
|
-
return fFirst === undefined ? fTail
|
|
133
|
+
return fFirst === undefined ? nodeOne(fTail) : { first: fFirst, tail: fTail }
|
|
135
134
|
}
|
|
136
135
|
|
|
137
136
|
/** @type {<I, O>(f: (value: I) => O|undefined) => (input: Sequence<I>) => Thunk<O>} */
|
|
@@ -148,14 +147,11 @@ const takeWhile = f => input => () => {
|
|
|
148
147
|
|
|
149
148
|
/** @type {<T>(f: (value: T) => boolean) => (input: Sequence<T>) => Thunk<T>} */
|
|
150
149
|
const dropWhile = f => input => () => {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
if (!f(first)) return result
|
|
157
|
-
i = tail
|
|
158
|
-
}
|
|
150
|
+
const result = next(input)
|
|
151
|
+
if (result === undefined) { return undefined }
|
|
152
|
+
const { first, tail } = result
|
|
153
|
+
if (f(first)) { return nodeOne(dropWhile(f)(tail)) }
|
|
154
|
+
return result
|
|
159
155
|
}
|
|
160
156
|
|
|
161
157
|
/** @type {<D>(def: D) => <T>(input: Sequence<T>) => D|T} */
|
|
@@ -293,6 +289,8 @@ module.exports = {
|
|
|
293
289
|
/** @readonly */
|
|
294
290
|
filter,
|
|
295
291
|
/** @readonly */
|
|
292
|
+
filterMap,
|
|
293
|
+
/** @readonly */
|
|
296
294
|
find,
|
|
297
295
|
/** @readonly */
|
|
298
296
|
some,
|
package/sequence/test.js
CHANGED
|
@@ -95,6 +95,18 @@ const stringify = sequence => json.stringify(sort)(_.toArray(sequence))
|
|
|
95
95
|
// stress tests
|
|
96
96
|
|
|
97
97
|
const stress = () => {
|
|
98
|
+
|
|
99
|
+
{
|
|
100
|
+
// 100_000_000 is too much
|
|
101
|
+
const n = 50_000_000
|
|
102
|
+
const result = _.toArray(_.countdown(n))
|
|
103
|
+
if (result.length !== n) { throw result.length }
|
|
104
|
+
const len = _.length(_.filter(x => x > n)(result))
|
|
105
|
+
if (len !== 0) { throw len }
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
console.log('first')
|
|
109
|
+
|
|
98
110
|
{
|
|
99
111
|
// 200_000_000 is too much
|
|
100
112
|
const n = 100_000_000
|
|
@@ -133,6 +145,17 @@ const stress = () => {
|
|
|
133
145
|
}
|
|
134
146
|
const a = _.next(sequence)
|
|
135
147
|
}
|
|
148
|
+
|
|
149
|
+
console.log('filterMap')
|
|
150
|
+
|
|
151
|
+
{
|
|
152
|
+
// 100_000_000 is too much
|
|
153
|
+
const n = 50_000_000
|
|
154
|
+
const result = _.toArray(_.countdown(n))
|
|
155
|
+
if (result.length !== n) { throw result.length }
|
|
156
|
+
const len = _.length(_.filterMap(() => undefined)(result))
|
|
157
|
+
if (len !== 0) { throw len }
|
|
158
|
+
}
|
|
136
159
|
}
|
|
137
160
|
|
|
138
161
|
stress()
|