Skip to content

Instantly share code, notes, and snippets.

@NotIntMan
Created August 21, 2020 07:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NotIntMan/0c711dd9abcf966d354d335985b2a9d6 to your computer and use it in GitHub Desktop.
Save NotIntMan/0c711dd9abcf966d354d335985b2a9d6 to your computer and use it in GitHub Desktop.
Transduction over arrays. Why doesn't we still use it?
interface Transducer<T, R> {
(source: Iterable<T>): Iterable<R>;
}
class IterableTransductor<T> implements Iterable<T> {
constructor(
private readonly source: Iterable<T>,
) {
}
[Symbol.iterator]() {
return this.source[Symbol.iterator]();
}
pipe(): IterableTransductor<T>
pipe<A>(a: Transducer<T, A>): IterableTransductor<A>
pipe<A, B>(a: Transducer<T, A>, b: Transducer<A, B>): IterableTransductor<B>
pipe<A, B, C>(a: Transducer<T, A>, b: Transducer<A, B>, c: Transducer<B, C>): IterableTransductor<C>
pipe<A, B, C, D>(a: Transducer<T, A>, b: Transducer<A, B>, c: Transducer<B, C>, d: Transducer<C, D>): IterableTransductor<D>
pipe(...transducers: Transducer<any, any>[]): IterableTransductor<any> {
const source = transducers.reduce((source, transducer) => transducer(source), this.source);
return new IterableTransductor(source);
}
toArray(): T[] {
return [...this];
}
}
function trans<T>(source: Iterable<T>): IterableTransductor<T> {
return new IterableTransductor(source);
}
function map<T, R>(mapper: (item: T) => R): Transducer<T, R> {
return function* (input) {
for (const item of input) {
yield mapper(item);
}
};
}
function filter<T>(filterer: (item: T) => boolean): Transducer<T, T> {
return function* (input) {
for (const item of input) {
if (filterer(item)) {
yield item;
}
}
};
}
function skip<T>(count: number): Transducer<T, T> {
return function* (input) {
const iterator = input[Symbol.iterator]();
for (let i = 0; i < count; i++) {
const iteration = iterator.next();
if (iteration.done) {
return;
}
}
while (true) {
const iteration = iterator.next();
if (iteration.done) {
return;
} else {
yield iteration.value;
}
}
};
}
function take<T>(count: number): Transducer<T, T> {
return function* (input) {
const iterator = input[Symbol.iterator]();
for (let i = 0; i < count; i++) {
const iteration = iterator.next();
if (iteration.done) {
return;
} else {
yield iteration.value;
}
}
};
}
function* range(from: number, to: number, step = 1) {
for (let i = from; i < to; i += step) {
yield i;
}
}
const data = trans(range(0, Infinity))
.pipe(
skip(5),
filter(x => (x % 2) == 0),
//map(x => x * 2 + 1),
take(20),
)
.toArray();
console.log(data);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment