data-collectors
Version:
A collection of composable reduction operations for arbitrary streams of values
112 lines (85 loc) • 3.35 kB
text/typescript
export interface Supplier<T> {
() : T;
}
export interface Accumulator<A, T> {
( container : A, item : T ) : void;
}
export interface Combinator<A> {
( first : A, second : A ) : A;
}
export interface Finisher<A, R> {
( container : A ) : R;
}
export interface Collector<T, A, R> {
supply () : A;
accumulate ( container : A, item : T ) : void;
combine ( container1 : A, container2 : A ) : A;
finish ( container : A ) : R;
then <U> ( transformer : ( result : R ) => U ) : Collector<T, A, U>;
apply ( iterable : Iterable<T> ) : R;
}
export class Collector<T, A, R> {
static of<T, A, R> ( supplier : Supplier<A>, accumulator : Accumulator<A, T>, combinator : Combinator<A>, finisher : Finisher<A, R> ) : Collector<T, A, R>;
static of<T, A> ( supplier : Supplier<A>, accumulator : Accumulator<A, T>, combinator : Combinator<A> ) : Collector<T, A, A>;
static of<T, A, R> ( supplier : Supplier<A>, accumulator : Accumulator<A, T>, combinator : Combinator<A>, finisher ?: Finisher<A, R> ) {
return new FunctionalCollector( supplier, accumulator, combinator, finisher || ( x => x as any ) );
}
}
export abstract class BaseCollector<T, A, R> implements Collector<T, A, R> {
abstract supply () : A;
abstract accumulate ( container : A, item : T ) : void;
abstract combine ( container1 : A, container2 : A ) : A;
abstract finish ( container : A ) : R;
then <U> ( transformer : ( result : R ) => U ) : Collector<T, A, U> {
return Collector.of(
this.supply.bind( this ),
this.accumulate.bind( this ),
this.combine.bind( this ),
( result : A ) => transformer( this.finish( result ) )
);
}
apply ( iterable : Iterable<T> ) : R {
const container = this.supply();
for ( let item of iterable ) {
this.accumulate( container, item );
}
return this.finish( container );
}
}
export class FunctionalCollector<T, A, R> extends BaseCollector<T, A, R> implements Collector<T, A, R> {
protected supplier : Supplier<A>;
protected accumulator : Accumulator<A, T>;
protected combinator : Combinator<A>;
protected finisher : Finisher<A, R>;
constructor ( supplier : Supplier<A>,
accumulator : Accumulator<A, T>,
combinator : Combinator<A>,
finisher : Finisher<A, R> ) {
super();
this.supplier = supplier;
this.accumulator = accumulator;
this.combinator = combinator;
this.finisher = finisher;
}
supply () : A {
return this.supplier();
}
accumulate ( container : A, item : T ) : void {
return this.accumulator( container, item );
}
combine ( container1 : A, container2 : A ) : A {
return this.combinator( container1, container2 );
}
finish ( container : A ) : R {
return this.finisher( container );
}
}
/**
* Applies a given collector to the given iterator's items
*
* @param iterable
* @param collector
*/
export function collect<T, R> ( iterable : Iterable<T>, collector : Collector<T, any, R> ) : R {
return collector.apply( iterable );
}