Created
August 21, 2020 07:52
-
-
Save NotIntMan/0c711dd9abcf966d354d335985b2a9d6 to your computer and use it in GitHub Desktop.
Transduction over arrays. Why doesn't we still use it?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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