1 | const { identity, isEven, isGreaterThan, modulus, digitize, not, compose,
|
2 | transduceArray, transduceAsyncIterator, transduceAsyncHasNextIterator, transduceGenerator,
|
3 | take, skip, mapping, filtering, eventing, sampling, passthrough, split, randomFilter, neighbors,
|
4 | makeAsyncRangeIterator, makeAsyncHasNextRangeIterator } = require('../dist/funprog.umd')
|
5 | const { nums, add1, sub1, concat, useNew, delay } = require('./utility.js')
|
6 |
|
7 | var assert = require('assert')
|
8 |
|
9 | const xform = compose(
|
10 | mapping(isGreaterThan(6)),
|
11 | mapping(add1),
|
12 | filtering(isEven)
|
13 |
|
14 |
|
15 | )
|
16 | describe('Given the functional programming library', function () {
|
17 | it('Then compose not and operation', async function () {
|
18 | var f = compose(not, sub1)
|
19 | assert.equal(true, await f(1))
|
20 | assert.equal(false, await f(0))
|
21 | })
|
22 | })
|
23 |
|
24 | describe('Given the transform functions', function () {
|
25 | it('Then mapping identity is a no-op', async function () {
|
26 | var f = mapping(identity)
|
27 | var rf = await f(concat)
|
28 | var val = await rf([1], [])
|
29 | assert.equal(1, val[0])
|
30 | })
|
31 | it('Then passthrough is a no-op', async function () {
|
32 | var f = passthrough()
|
33 | var rf = await f(concat)
|
34 | var val = await rf([1], [])
|
35 | assert.equal(1, val[0])
|
36 | })
|
37 | it('Then randomFilter(1) is always includes', async function () {
|
38 | var f = randomFilter(1)
|
39 | var rf = await f(concat)
|
40 | var val = await rf([], 1)
|
41 | assert.equal(1, val.length)
|
42 | })
|
43 | it('Then randomFilter(0) is always eliminates', async function () {
|
44 | var f = randomFilter(-1)
|
45 | var rf = await f(concat)
|
46 | var val = await rf([], 1)
|
47 | assert.ok(val.reduced === null)
|
48 | })
|
49 | })
|
50 |
|
51 | describe('Given the functional programming library', function () {
|
52 | it('Then able to synchronously transduce from an array', async function () {
|
53 | const tform = compose(
|
54 | mapping(compose(not, sub1)),
|
55 | take(1))
|
56 | const result = await transduceArray(tform, concat, [], nums)
|
57 | assert.equal(result.toString(), [true].toString())
|
58 | })
|
59 | it('Then able to synchronously transduce from an array', async function () {
|
60 | const result = await transduceArray(xform, concat, [], nums)
|
61 | assert.equal(result.toString(), [8, 10].toString())
|
62 | })
|
63 | it('Then able to asynchronously transduce from an interator', async function () {
|
64 | const deltaxform = compose(
|
65 | mapping(identity)
|
66 | )
|
67 | const numsIt = makeAsyncRangeIterator(1, 10)
|
68 | var result = await transduceAsyncIterator(deltaxform, concat, [], numsIt)
|
69 | assert.equal(result.toString(), [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ].toString())
|
70 | })
|
71 | it('Then able to asynchronously transduce from an hasNext interator', async function () {
|
72 | const deltaxform = compose(
|
73 | mapping(identity)
|
74 | )
|
75 | const numsIt = makeAsyncHasNextRangeIterator(1, 10)
|
76 | var result = await transduceAsyncHasNextIterator(deltaxform, concat, [], numsIt)
|
77 | assert.equal(result.toString(), [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ].toString())
|
78 | })
|
79 | it('Then able to asynchronously take from hasNext interator', async function () {
|
80 | const deltaxform = compose(
|
81 | take(3),
|
82 | mapping(identity)
|
83 | )
|
84 | const numsIt = makeAsyncHasNextRangeIterator(1, 10)
|
85 | var result = await transduceAsyncHasNextIterator(deltaxform, concat, [], numsIt)
|
86 | assert.equal(result.toString(), [1, 2, 3].toString())
|
87 | })
|
88 | it('Then able to asynchronously skip from hasNext interator', async function () {
|
89 | const deltaxform = compose(
|
90 | skip(6),
|
91 | mapping(identity)
|
92 | )
|
93 | const numsIt = makeAsyncHasNextRangeIterator(1, 10)
|
94 | var result = await transduceAsyncHasNextIterator(deltaxform, concat, [], numsIt)
|
95 | assert.equal(result.toString(), [7, 8, 9].toString())
|
96 | })
|
97 | it('Then able to asynchronously detect events from a stream', async function () {
|
98 | const deltaxform = compose(
|
99 | mapping(modulus(3)),
|
100 | eventing(digitize)
|
101 | )
|
102 | const numsIt = makeAsyncHasNextRangeIterator(1, 10)
|
103 | var result = await transduceAsyncHasNextIterator(deltaxform, concat, [], numsIt)
|
104 | assert.equal(result[1].start, 3)
|
105 | assert.equal(result[1].end, 4)
|
106 | })
|
107 | it('Then able build a transformed generator', async function () {
|
108 | const deltaxform = compose(
|
109 | skip(3),
|
110 | mapping(modulus(3))
|
111 | )
|
112 | const generator = makeAsyncRangeIterator(1, 10)
|
113 | var newgenerator = await transduceGenerator(deltaxform, useNew, null, generator)
|
114 | for await (const value of newgenerator) {
|
115 | assert.equal(value, 1)
|
116 | break
|
117 | }
|
118 | })
|
119 | it('Then able sample from generator', async function () {
|
120 | const deltaxform = sampling(300)
|
121 | const generator = makeAsyncRangeIterator(1, 10, 1, 100)
|
122 | var newgenerator = await transduceGenerator(deltaxform, useNew, null, generator)
|
123 | var cnt = 0
|
124 | var last = null
|
125 |
|
126 | for await (const value of newgenerator) {
|
127 | cnt++
|
128 | if (cnt >= 3) {
|
129 | last = value
|
130 | break
|
131 | }
|
132 | }
|
133 | assert.equal(last, 7)
|
134 | })
|
135 | it('Then able to split from generator', async function () {
|
136 | var duplicate = function (x) {
|
137 | return [x, x]
|
138 | }
|
139 | var deltaxform = compose(
|
140 | mapping(identity),
|
141 | split(duplicate),
|
142 | filtering(isEven),
|
143 | take(5)
|
144 | )
|
145 |
|
146 | const generator = makeAsyncRangeIterator(1, 10)
|
147 | var newgenerator = await transduceGenerator(deltaxform, useNew, null, generator)
|
148 | var stream = []
|
149 | for await (const value of newgenerator) {
|
150 | stream.push(value)
|
151 | }
|
152 |
|
153 | assert.equal(stream[0], 2)
|
154 | assert.equal(stream[1], 2)
|
155 | assert.equal(stream[2], 4)
|
156 | assert.equal(stream[4], 6)
|
157 | })
|
158 | it('Then use neighbors to get average of n to n+5 records inclusive of itself as n record is processed', async function () {
|
159 | var enrich = function (x) {
|
160 | let sum = x.neighbors.reduce((x, y) => x + y, 0)
|
161 | let avg = sum / x.neighbors.length
|
162 | let diff = x.data - avg
|
163 | return {
|
164 | data: x.data,
|
165 | diff: diff
|
166 | }
|
167 | }
|
168 | var deltaxform = compose(
|
169 | mapping(identity),
|
170 | neighbors(5),
|
171 | mapping(enrich)
|
172 | )
|
173 | const generator = makeAsyncRangeIterator(1, 10)
|
174 | var newgenerator = await transduceGenerator(deltaxform, useNew, null, generator)
|
175 | var stream = []
|
176 | for await (const value of newgenerator) {
|
177 | stream.push(value)
|
178 | }
|
179 | assert.equal(stream[0].data, 1)
|
180 | assert.equal(stream[0].diff, -2)
|
181 | assert.equal(stream[1].data, 2)
|
182 | assert.equal(stream[1].diff, -2)
|
183 | assert.equal(stream[2].data, 3)
|
184 | assert.equal(stream[2].diff, -2)
|
185 | assert.equal(stream[3].data, 4)
|
186 | assert.equal(stream[3].diff, -2)
|
187 | })
|
188 | })
|