functionalscript 0.0.212 → 0.0.217

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/function/index.js CHANGED
@@ -8,11 +8,11 @@
8
8
  const compose = f => g => x => f(g(x))
9
9
 
10
10
  /** @type {<T>(value: T) => T} */
11
- const id = value => value
11
+ const identity = value => value
12
12
 
13
13
  module.exports = {
14
14
  /** @readonly */
15
- id,
15
+ identity,
16
16
  /** @readonly */
17
17
  compose,
18
18
  }
package/json/test.js CHANGED
@@ -1,6 +1,6 @@
1
1
  const json = require('.')
2
2
  const { sort } = require('../object')
3
- const { id } = require('../function')
3
+ const { identity } = require('../function')
4
4
 
5
5
  if (json.addProperty("Hello")([])({}) !== "Hello") { throw 'error' }
6
6
 
@@ -10,7 +10,7 @@ if (json.addProperty("Hello")([])({}) !== "Hello") { throw 'error' }
10
10
  }
11
11
 
12
12
  {
13
- const x = json.stringify(id)(json.addProperty("Hello")(['a'])({}))
13
+ const x = json.stringify(identity)(json.addProperty("Hello")(['a'])({}))
14
14
  if (x !== '{"a":"Hello"}') { throw x }
15
15
  }
16
16
 
@@ -20,7 +20,7 @@ if (json.addProperty("Hello")([])({}) !== "Hello") { throw 'error' }
20
20
  }
21
21
 
22
22
  {
23
- const x = json.stringify(id)(json.addProperty("Hello")(['a'])({ c: [], b: 12 }))
23
+ const x = json.stringify(identity)(json.addProperty("Hello")(['a'])({ c: [], b: 12 }))
24
24
  if (x !== '{"c":[],"b":12,"a":"Hello"}') { throw x }
25
25
  }
26
26
 
@@ -34,6 +34,6 @@ if (json.addProperty("Hello")([])({}) !== "Hello") { throw 'error' }
34
34
  {
35
35
  const _0 = { a: { y: [24] }, c: [], b: 12 }
36
36
  const _1 = json.addProperty("Hello")(['a', 'x'])(_0)
37
- const _2 = json.stringify(id)(_1)
37
+ const _2 = json.stringify(identity)(_1)
38
38
  if (_2 !== '{"a":{"y":[24],"x":"Hello"},"c":[],"b":12}') { throw _2 }
39
39
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.212",
3
+ "version": "0.0.217",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/sequence/index.js CHANGED
@@ -18,7 +18,7 @@ const { logicalNot, strictEqual } = require('../function/operator')
18
18
  *
19
19
  * Please note that the sequence also contains `Concat<T>. We need this as
20
20
  * a workaround because modern JavaScript implementations don't support
21
- * ES6 TCO (Tail Call Optimization). Without this wotkaround we may have
21
+ * ES6 TCO (Tail Call Optimization). Without this workaround, we may have
22
22
  * a stack overflow if a list contains a lot of concateneted lists.
23
23
  *
24
24
  * @template T
@@ -37,6 +37,9 @@ const { logicalNot, strictEqual } = require('../function/operator')
37
37
 
38
38
  const empty = () => undefined
39
39
 
40
+ /** @type {<T>(first: T) => (tail: Sequence<T>) => Sequence<T>} */
41
+ const sequence = first => tail => () => [first, tail]
42
+
40
43
  /** @type {<F, T>(a: readonly[F, Sequence<T>]) => (b: Sequence<T>) => readonly[F, Sequence<T>]} */
41
44
  const norm = ([a0, a1]) => b => [a0, [a1, b]]
42
45
 
@@ -78,7 +81,7 @@ const first = input => {
78
81
  */
79
82
 
80
83
  /**
81
- * Note: the operation is not lazy. It traverse the given array and creates a linked list.
84
+ * Note: the operation is not lazy. It traverses the given array and creates a linked list.
82
85
  *
83
86
  * @type {<T>(...array: readonly T[]) => Sequence<T>}
84
87
  */
@@ -86,14 +89,12 @@ const list = (...array) => {
86
89
  /** @typedef {typeof array extends readonly(infer T)[] ? T : never} T */
87
90
  let i = array.length
88
91
  /** @type {Sequence<T>} */
89
- let result = empty
92
+ let iResult = empty
90
93
  while (i !== 0) {
91
94
  i = i - 1
92
- /** @type {FirstAndTail<T>} */
93
- const listResult = [array[i], result]
94
- result = () => listResult
95
+ iResult = sequence(array[i])(iResult)
95
96
  }
96
- return result
97
+ return iResult
97
98
  }
98
99
 
99
100
  /** @type {<T>(...array: readonly Sequence<T>[]) => Sequence<T>} */
@@ -184,8 +185,8 @@ const last = def => input => {
184
185
  /** @type {<T, R>(s: seqOp.ExclusiveScan<T, R>) => (input: Sequence<T>) => R} */
185
186
  const reduce = ([first, s]) => input => last(first)(scan(s)(input))
186
187
 
187
- /** @type {<T, R>(ro: op.ReduceOperator<R, T>) => (first: R) => (input: Sequence<T>) => R} */
188
- const fold = ro => first => reduce(seqOp.exclusiveScan(ro)(first))
188
+ /** @type {<T, R>(operator: op.ReduceOperator<R, T>) => (first: R) => (input: Sequence<T>) => R} */
189
+ const fold = operator => first => reduce(seqOp.exclusiveScan(operator)(first))
189
190
 
190
191
  const entries = scan(seqOp.entries)
191
192
 
@@ -265,6 +266,20 @@ const zip = a => b => () => {
265
266
  return [[resultA[0], resultB[0]], zip(resultA[1])(resultB[1])]
266
267
  }
267
268
 
269
+ /** @type {<T>(s: Sequence<T>) => Sequence<T>} */
270
+ const reverse = s => {
271
+ /** @type {typeof s} */
272
+ let iResult = empty
273
+ let iSource = s
274
+ while (true) {
275
+ const result = next(iSource)
276
+ if (result === undefined) { return iResult }
277
+ const [first, tail] = result
278
+ iResult = sequence(first)(iResult)
279
+ iSource = tail
280
+ }
281
+ }
282
+
268
283
  module.exports = {
269
284
  /** @readonly */
270
285
  next,
@@ -273,6 +288,8 @@ module.exports = {
273
288
  /** @readonly */
274
289
  empty,
275
290
  /** @readonly */
291
+ sequence,
292
+ /** @readonly */
276
293
  at,
277
294
  /** @readonly */
278
295
  concat,
@@ -326,4 +343,6 @@ module.exports = {
326
343
  includes,
327
344
  /** @readonly */
328
345
  zip,
346
+ /** @readonly */
347
+ reverse,
329
348
  }
@@ -0,0 +1,41 @@
1
+ # Operator
2
+
3
+ ## Sequence
4
+
5
+ ```ts
6
+ type Sequence<T> = SubSequence<T, undefined>
7
+ ```
8
+
9
+ ## SubSequence
10
+
11
+ ```ts
12
+ type SubSequence<T, C> = () => SubSequenceResult<T, C>
13
+ type SubSequenceResult<T, C> = [T, SubSequence<T, C>] | [C]
14
+ ```
15
+
16
+ ## The Main FlatScan Operator
17
+
18
+ ```ts
19
+ type FlatScanOperator<T, A> = (value: T) => SubSequence<A, FlatScanOp<T, A>>
20
+
21
+ const flatScanConcat
22
+ : SubSequence<A, FlatScanOp<T, A>> => Sequence<T> => Sequence<A>
23
+ => a => b => () => {
24
+ switch (next(a)) {
25
+ case [first, tail]: { return [first, flatScanConcat(tail)(b)] }
26
+ case [operator]: { return flatScan(operator)(b)() }
27
+ }
28
+ }
29
+
30
+ const flatScan
31
+ : FlatScanOperator<T, A> => Sequence<T> => Sequence<A>
32
+ => operator => sequence => () => {
33
+ // optimization for `takeWhile`, `find`
34
+ if (operator === flatScanEmpty) { return [undefined] }
35
+ //
36
+ switch (next(s)) {
37
+ case [first, tail]: { return flatScanConcat(operator(first))(tail)() }
38
+ case [undefined]: { return [undefined] }
39
+ }
40
+ }
41
+ ```
package/sequence/test.js CHANGED
@@ -1,12 +1,15 @@
1
1
  const seq = require('.')
2
+ const { empty, next, list, flatMap, concat, exclusiveScan, find, every, some, first, drop, map, generate } = require('.')
2
3
  const { sum } = require('./operator')
3
4
  const array = require('./array')
5
+ const json = require('../json')
6
+ const { identity } = require('../function')
4
7
 
5
8
  /** @type {<T>(input: seq.Sequence<T>) => void} */
6
9
  const print = input => {
7
10
  let i = input
8
11
  while (true) {
9
- const result = seq.next(i)
12
+ const result = next(i)
10
13
  if (result === undefined) { return }
11
14
  console.log(result[0])
12
15
  i = result[1]
@@ -14,47 +17,47 @@ const print = input => {
14
17
  }
15
18
 
16
19
  {
17
- const big = seq.list(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 42, 60)
18
- const list0 = seq.list(0, 1, 2, 3)
19
- const list1 = seq.flatMap(x => seq.list(x, x * 2, x * 3))(list0)
20
- const list2 = seq.concat(list0, list0)
21
- const list3 = seq.exclusiveScan(sum)(list0)
22
- const r = seq.find(x => x === 42)(big)
23
- if (seq.every(x => x > 0)(big) !== true) { throw 'x'}
24
- if (seq.every(x => x < 20)(big) !== false) { throw 'x' }
25
- if (seq.some(x => x > 100)(big) !== false) { throw 'x' }
26
- if (seq.some(x => x > 50)(big) !== true) { throw 'x' }
27
- if (seq.first(seq.drop(16)(big)) !== 42) { throw 'drop'}
20
+ const big = list(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 42, 60)
21
+ const list0 = list(0, 1, 2, 3)
22
+ const list1 = flatMap(x => list(x, x * 2, x * 3))(list0)
23
+ const list2 = concat(list0, list0)
24
+ const list3 = exclusiveScan(sum)(list0)
25
+ const r = find(x => x === 42)(big)
26
+ if (every(x => x > 0)(big) !== true) { throw 'x' }
27
+ if (every(x => x < 20)(big) !== false) { throw 'x' }
28
+ if (some(x => x > 100)(big) !== false) { throw 'x' }
29
+ if (some(x => x > 50)(big) !== true) { throw 'x' }
30
+ if (first(drop(16)(big)) !== 42) { throw 'drop' }
28
31
  {
29
- const a = seq.map(seq.generate)(seq.generate(100_000))
32
+ const a = map(generate)(generate(100_000))
30
33
  const ar = array.fromSequence(a)
31
- // This operation use a lot of stack because `...`
34
+ // This operation uses a lot of stack because `...`
32
35
  // puts array items on a stack.
33
36
  // Use `array.sequence` instead
34
- const x = seq.concat(...ar)
35
- const r = seq.next(x)
37
+ const x = concat(...ar)
38
+ const r = next(x)
36
39
  // print(x)
37
40
  }
38
41
  {
39
- const a = array.fromSequence(seq.generate(1_000_000))
40
- let x = seq.concat(array.sequence(a), big)
41
- const r = seq.next(x)
42
+ const a = array.fromSequence(generate(1_000_000))
43
+ let x = concat(array.sequence(a), big)
44
+ const r = next(x)
42
45
  // print(x)
43
46
  }
44
47
  {
45
48
  let x = big
46
49
  for (let i = 0; i < 1_000_000; ++i) {
47
- x = seq.concat(seq.empty, x)
50
+ x = concat(empty, x)
48
51
  }
49
- const r = seq.next(x)
52
+ const r = next(x)
50
53
  // print(x)
51
- }
54
+ }
52
55
  {
53
56
  let x = big
54
57
  for (let i = 0; i < 1_000_000; ++i) {
55
- x = seq.concat(x, seq.list(i))
58
+ x = concat(x, list(i))
56
59
  }
57
- const r = seq.next(x)
60
+ const r = next(x)
58
61
  // print(x)
59
62
  }
60
63
  }
@@ -63,3 +66,10 @@ const print = input => {
63
66
  const x = seq.join(':')(seq.list("1", "2", "3", "4", "5", "6"))
64
67
  if (x !== "1:2:3:4:5:6") { throw x }
65
68
  }
69
+
70
+ {
71
+ const r = seq.reverse(seq.list(1, 2, 3, 4))
72
+ const s = array.fromSequence(r)
73
+ const j = json.stringify(identity)(s)
74
+ if (j !== '[4,3,2,1]') { throw j }
75
+ }