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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.224",
3
+ "version": "0.0.230",
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
 
@@ -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 => {
@@ -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>) => (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: 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