jducers
A js transducers-like implementation using generators and async generators.
A composed function expecting a combination function to make a reducer is called transducer.
Transducers are useful to compose adjacent map(), filer() and reduce() operations together to improve performaces.
A jducer is similar to a transducer because it is a composed function and can be used to compose map(), filer() and reduce() operations together, but there are some differences.
It was a challenge against myself to see how far could I go using generators.
install
$ npm i --save jducers
utility
A little fp utility library used by jducers and available for you with pipe, compose, curry, partial and partialRight
import { pipe, compose, curry, partial, partialRight } from 'jducers/src/utility';
sync
Sync's jducers helpers:
import { map, filter, reduce, run } from 'jducers/src/jducers/sync'
or
import * as SJ from 'jducers/src/jducers/sync'
- map: accepts only a mapper function that is up to you and returns a function used in the creation of a jducer
- filter: accepts only a predicate function that is up to you and returns a function used in the creation of a jducer
- reduce: accepts two parameters: a reducer function with some constraints and an optional initial value and returns a function used in the creation of a jducer. The reducer function will be called with only two parameters: the accumulator and the current processed value
- run: accepts two parameters: a composition (you can use pipe or compose from my utility library) and a sync iterable like an array. Returns the resuling array or a single value.It depends on the functions used in the composition
import * as SJ from 'jducers/src/jducers/sync'
import { pipe, partialRight } from 'jducers/src/utility';
let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
const isOdd = i => !!(i % 2);
const double = i => i * 2;
const sum = (acc, val) => acc + val;
const syncIsOddFilter = SJ.filter(isOdd);
const syncDoubleMap = SJ.map(double);
const syncSumReduce = SJ.reduce(sum);
const run = partialRight(SJ.run, array);
let jducer = pipe(syncIsOddFilter, syncDoubleMap);
let res = run(jducer);
console.log(res);
jducer = pipe(syncIsOddFilter, syncDoubleMap, syncSumReduce);
res = run(jducer);
console.log(res);
async
Async's jducers helpers (useful for async iterables and concurrent iterations):
import { map, filter, reduce, run, observerFactory } from 'jducers/src/jducers/async'
or
import * as AJ from 'jducers/src/jducers/async'
- map: accepts only a mapper function that is up to you and returns a function used in the creation of a jducer
- filter: accepts only a predicate function that is up to you and returns a function used in the creation of a jducer
- reduce: accepts two parameters: a reducer function with some constraints and an optional initial value and returns a function used in the creation of a jducer. The reducer function will be called with only two parameters: the accumulator and the current processed value
- run: accepts two parameters: a composition (you can use pipe or compose from my utility library) and an async iterable like an array of promises. Returns a promise that will be fulfilled with the resulting array or a single value. It depends on the functions used in the composition
- observerFactory: accepts one or more callbacks and returns a simple observer that calls them when each single value of our async iterable flows through it. The observer has to be placed in a composition to form the jducer
import * as AJ from 'jducers/src/jducers/async'
import { pipe, partialRight } from 'jducers/src/utility';
const asyncArray = {
array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
[Symbol.asyncIterator]: async function* () {
for (const x of this.array) {
await new Promise(ok => setTimeout(() => ok(x), 2000));
yield x;
}
}
}
const isOdd = i => !!(i % 2);
const double = i => i * 2;
const sum = (acc, val) => acc + val;
const asyncIsOddFilter = AJ.filter(isOdd);
const asyncDoubleMap = AJ.map(double);
const asyncSumReduce = AJ.reduce(sum);
const run = partialRight(AJ.run, asyncArray);
let jducer = pipe(asyncIsOddFilter, asyncDoubleMap);
let res = run(jducer);
res.then(x => console.log(x));
jducer = pipe(asyncIsOddFilter, asyncDoubleMap, asyncSumReduce);
res = run(jducer);;
res.then(x => console.log(x));
const observer = AJ.observerFactory(console.log);
jducer = pipe(observer, asyncDoubleMap, observer, asyncSumReduce);
res = run(jducer);
res.then(x => console.log(x));
weight
All modules and functions together are 3.284Kb without compression
License
MIT