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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.227",
3
+ "version": "0.0.231",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "index.js",
6
6
  "scripts": {
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 result = node(a)
62
- if (result === undefined) {
64
+ const aNode = node(a)
65
+ if (aNode === undefined) {
63
66
  i = b
64
- } else if (result instanceof Array) {
65
- const [aa, ab] = result
67
+ } else if (aNode instanceof Array) {
68
+ const [aa, ab] = aNode
66
69
  i = () => [aa, () => [ab, b]]
67
70
  } else {
68
- const { first, tail } = result
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 => input => () => {
141
- const result = next(input)
142
- if (result === undefined) { return undefined }
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
- if (!f(first)) { return undefined }
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 => input => () => {
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>} ScanFunc
201
+ * @typedef {(value: T) => ScanState<T, A>} ScanOperator
202
202
  */
203
203
 
204
204
  /**
205
205
  * @template T,A
206
- * @typedef {readonly[A, ScanFunc<T, A>]} ScanState
206
+ * @typedef {readonly[A, ScanOperator<T, A>]} ScanState
207
207
  */
208
208
 
209
- /** @type {<T,A>(operator: ScanFunc<T, A>) => (input: Sequence<T>) => Thunk<A>} */
210
- const scan = operator => input => () => {
211
- const result = next(input)
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) }
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: ScanFunc<T, A>) => <D>(def: D)=> (input: Sequence<T>) => D|A} */
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, scanFunc(operator)(init)]
227
+ const scanState = operator => init => [init, scanOperator(operator)(init)]
228
228
 
229
- /** @type {<T,A>(operator: ReduceOperator<T, A>) => (init: A) => ScanFunc<T, A>} */
230
- const scanFunc = operator => init => value => {
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(scanFunc(operator)(init))(init)
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()