functionalscript 0.0.227 → 0.0.231
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 +42 -32
- package/sequence/test.js +21 -0
package/package.json
CHANGED
package/sequence/index.js
CHANGED
|
@@ -34,6 +34,9 @@ const op = require('../function/operator')
|
|
|
34
34
|
|
|
35
35
|
const empty = () => undefined
|
|
36
36
|
|
|
37
|
+
/** @type {<T>(first: T) => (tail: Sequence<T>) => Sequence<T>} */
|
|
38
|
+
const sequence = first => tail => () => ({ first, tail })
|
|
39
|
+
|
|
37
40
|
/** @type {<T>(sequence: Sequence<T>) => Node<T>} */
|
|
38
41
|
const nodeOne = sequence => [empty, sequence]
|
|
39
42
|
|
|
@@ -58,14 +61,14 @@ const next = sequence => {
|
|
|
58
61
|
const n = node(i)
|
|
59
62
|
if (!(n instanceof Array)) { return n }
|
|
60
63
|
const [a, b] = n
|
|
61
|
-
const
|
|
62
|
-
if (
|
|
64
|
+
const aNode = node(a)
|
|
65
|
+
if (aNode === undefined) {
|
|
63
66
|
i = b
|
|
64
|
-
} else if (
|
|
65
|
-
const [aa, ab] =
|
|
67
|
+
} else if (aNode instanceof Array) {
|
|
68
|
+
const [aa, ab] = aNode
|
|
66
69
|
i = () => [aa, () => [ab, b]]
|
|
67
70
|
} else {
|
|
68
|
-
const { first, tail } =
|
|
71
|
+
const { first, tail } = aNode
|
|
69
72
|
return { first, tail: () => [tail, b] }
|
|
70
73
|
}
|
|
71
74
|
}
|
|
@@ -136,23 +139,20 @@ const filterMapFn = f => ({first, tail}) => {
|
|
|
136
139
|
/** @type {<I, O>(f: (value: I) => O|undefined) => (input: Sequence<I>) => Thunk<O>} */
|
|
137
140
|
const filterMap = f => nextMap(filterMapFn(f))
|
|
138
141
|
|
|
142
|
+
/** @type {<T>(f: (value: T) => boolean) => (result: ResultOne<T>) => Node<T>} */
|
|
143
|
+
const takeWhileFn = f => ({ first, tail }) => f(first) ? { first, tail: takeWhile(f)(tail) } :undefined
|
|
144
|
+
|
|
139
145
|
/** @type {<T>(f: (value: T) => boolean) => (input: Sequence<T>) => Thunk<T>} */
|
|
140
|
-
const takeWhile = f =>
|
|
141
|
-
|
|
142
|
-
|
|
146
|
+
const takeWhile = f => nextMap(takeWhileFn(f))
|
|
147
|
+
|
|
148
|
+
/** @type {<T>(f: (value: T) => boolean) => (result: ResultOne<T>) => Node<T>} */
|
|
149
|
+
const dropWhileFn = f => result => {
|
|
143
150
|
const { first, tail } = result
|
|
144
|
-
|
|
145
|
-
return { first, tail: takeWhile(f)(result.tail) }
|
|
151
|
+
return f(first) ? nodeOne(dropWhile(f)(tail)) : result
|
|
146
152
|
}
|
|
147
153
|
|
|
148
154
|
/** @type {<T>(f: (value: T) => boolean) => (input: Sequence<T>) => Thunk<T>} */
|
|
149
|
-
const dropWhile = f =>
|
|
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
|
|
155
|
-
}
|
|
155
|
+
const dropWhile = f => nextMap(dropWhileFn(f))
|
|
156
156
|
|
|
157
157
|
/** @type {<D>(def: D) => <T>(input: Sequence<T>) => D|T} */
|
|
158
158
|
const first = def => input => {
|
|
@@ -198,24 +198,24 @@ const countdown = count => () => {
|
|
|
198
198
|
|
|
199
199
|
/**
|
|
200
200
|
* @template T,A
|
|
201
|
-
* @typedef {(value: T) => ScanState<T, A>}
|
|
201
|
+
* @typedef {(value: T) => ScanState<T, A>} ScanOperator
|
|
202
202
|
*/
|
|
203
203
|
|
|
204
204
|
/**
|
|
205
205
|
* @template T,A
|
|
206
|
-
* @typedef {readonly[A,
|
|
206
|
+
* @typedef {readonly[A, ScanOperator<T, A>]} ScanState
|
|
207
207
|
*/
|
|
208
208
|
|
|
209
|
-
/** @type {<T,A>(operator:
|
|
210
|
-
const
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
const { first, tail } = result
|
|
214
|
-
const r = operator(first)
|
|
215
|
-
return { first: r[0], tail: scan(r[1])(tail) }
|
|
209
|
+
/** @type {<T,A>(operator: ScanOperator<T, A>) => (result: ResultOne<T>) => Node<A>} */
|
|
210
|
+
const scanFn = operator => ({first, tail}) => {
|
|
211
|
+
const [value, nextOperator] = operator(first)
|
|
212
|
+
return { first: value, tail: scan(nextOperator)(tail) }
|
|
216
213
|
}
|
|
217
214
|
|
|
218
|
-
/** @type {<T,A>(operator:
|
|
215
|
+
/** @type {<T,A>(operator: ScanOperator<T, A>) => (input: Sequence<T>) => Thunk<A>} */
|
|
216
|
+
const scan = operator => nextMap(scanFn(operator))
|
|
217
|
+
|
|
218
|
+
/** @type {<T,A>(operator: ScanOperator<T, A>) => <D>(def: D)=> (input: Sequence<T>) => D|A} */
|
|
219
219
|
const scanReduce = operator => def => input => last(def)(scan(operator)(input))
|
|
220
220
|
|
|
221
221
|
/**
|
|
@@ -224,16 +224,16 @@ const scanReduce = operator => def => input => last(def)(scan(operator)(input))
|
|
|
224
224
|
*/
|
|
225
225
|
|
|
226
226
|
/** @type {<T,A>(operator: ReduceOperator<T, A>) => (init: A) => ScanState<T, A>} */
|
|
227
|
-
const scanState = operator => init => [init,
|
|
227
|
+
const scanState = operator => init => [init, scanOperator(operator)(init)]
|
|
228
228
|
|
|
229
|
-
/** @type {<T,A>(operator: ReduceOperator<T, A>) => (init: A) =>
|
|
230
|
-
const
|
|
229
|
+
/** @type {<T,A>(operator: ReduceOperator<T, A>) => (init: A) => ScanOperator<T, A>} */
|
|
230
|
+
const scanOperator = operator => init => value => {
|
|
231
231
|
const result = operator(init)(value)
|
|
232
232
|
return scanState(operator)(result)
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
/** @type {<T,A>(operator: ReduceOperator<T, A>) => (init: A) => (input: Sequence<T>) => A} */
|
|
236
|
-
const reduce = operator => init => scanReduce(
|
|
236
|
+
const reduce = operator => init => scanReduce(scanOperator(operator)(init))(init)
|
|
237
237
|
|
|
238
238
|
/**
|
|
239
239
|
* @template T
|
|
@@ -265,10 +265,18 @@ const entryOp = index => value => [[index, value], entryOp(index + 1)]
|
|
|
265
265
|
/** @type {<T>(input: Sequence<T>) => Thunk<Entry<T>>} */
|
|
266
266
|
const entries = scan(entryOp(0))
|
|
267
267
|
|
|
268
|
+
/** @type {<T>(prior: Sequence<T>) => (value: T) => Sequence<T>} */
|
|
269
|
+
const reverseOp = prior => value => sequence(value)(prior)
|
|
270
|
+
|
|
271
|
+
/** @type {<T>(input: Sequence<T>) => Sequence<T>} */
|
|
272
|
+
const reverse = reduce(reverseOp)(empty)
|
|
273
|
+
|
|
268
274
|
module.exports = {
|
|
269
275
|
/** @readonly */
|
|
270
276
|
empty,
|
|
271
277
|
/** @readonly */
|
|
278
|
+
sequence,
|
|
279
|
+
/** @readonly */
|
|
272
280
|
iterable,
|
|
273
281
|
/** @readonly */
|
|
274
282
|
next,
|
|
@@ -303,7 +311,7 @@ module.exports = {
|
|
|
303
311
|
/** @readonly */
|
|
304
312
|
dropWhile,
|
|
305
313
|
/** @readonly */
|
|
306
|
-
scanFunc,
|
|
314
|
+
scanFunc: scanOperator,
|
|
307
315
|
/** @readonly */
|
|
308
316
|
scanState,
|
|
309
317
|
/** @readonly */
|
|
@@ -321,5 +329,7 @@ module.exports = {
|
|
|
321
329
|
/** @readonly */
|
|
322
330
|
length,
|
|
323
331
|
/** @readonly */
|
|
332
|
+
reverse,
|
|
333
|
+
/** @readonly */
|
|
324
334
|
countdown,
|
|
325
335
|
}
|
package/sequence/test.js
CHANGED
|
@@ -92,6 +92,16 @@ const stringify = sequence => json.stringify(sort)(_.toArray(sequence))
|
|
|
92
92
|
if (result !== '[[0,"hello"],[1,"world"]]') { throw result }
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
{
|
|
96
|
+
const result = stringify(_.reverse([]))
|
|
97
|
+
if (result !== '[]') { throw result }
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
{
|
|
101
|
+
const result = stringify(_.reverse([1,2,3,4,5]))
|
|
102
|
+
if (result !== '[5,4,3,2,1]') { throw result }
|
|
103
|
+
}
|
|
104
|
+
|
|
95
105
|
// stress tests
|
|
96
106
|
|
|
97
107
|
const stress = () => {
|
|
@@ -156,6 +166,17 @@ const stress = () => {
|
|
|
156
166
|
const len = _.length(_.filterMap(() => undefined)(result))
|
|
157
167
|
if (len !== 0) { throw len }
|
|
158
168
|
}
|
|
169
|
+
|
|
170
|
+
console.log('dropWhile')
|
|
171
|
+
|
|
172
|
+
{
|
|
173
|
+
// 50_000_000 is too much
|
|
174
|
+
const n = 20_000_000
|
|
175
|
+
const result = _.toArray(_.countdown(n))
|
|
176
|
+
if (result.length !== n) { throw result.length }
|
|
177
|
+
const len = _.length(_.dropWhile(() => true)(result))
|
|
178
|
+
if (len !== 0) { throw len }
|
|
179
|
+
}
|
|
159
180
|
}
|
|
160
181
|
|
|
161
182
|
// stress()
|