functionalscript 0.0.224 → 0.0.230
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 +29 -19
- package/sequence/test.js +22 -1
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
|
|
|
@@ -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 => {
|
|
@@ -206,15 +206,15 @@ const countdown = count => () => {
|
|
|
206
206
|
* @typedef {readonly[A, ScanFunc<T, A>]} ScanState
|
|
207
207
|
*/
|
|
208
208
|
|
|
209
|
-
/** @type {<T,A>(operator: ScanFunc<T, A>) => (
|
|
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: ScanFunc<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
|
|
|
215
|
+
/** @type {<T,A>(operator: ScanFunc<T, A>) => (input: Sequence<T>) => Thunk<A>} */
|
|
216
|
+
const scan = operator => nextMap(scanFn(operator))
|
|
217
|
+
|
|
218
218
|
/** @type {<T,A>(operator: ScanFunc<T, A>) => <D>(def: D)=> (input: Sequence<T>) => D|A} */
|
|
219
219
|
const scanReduce = operator => def => input => last(def)(scan(operator)(input))
|
|
220
220
|
|
|
@@ -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,
|
|
@@ -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,9 +166,20 @@ 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
|
-
stress()
|
|
182
|
+
// stress()
|
|
162
183
|
|
|
163
184
|
module.exports = {
|
|
164
185
|
|