Skip to content

Commit

Permalink
feat: add .reducer factory method to collections
Browse files Browse the repository at this point in the history
  • Loading branch information
vitoke committed Jul 11, 2021
1 parent d25784e commit 5eb2976
Show file tree
Hide file tree
Showing 48 changed files with 971 additions and 32 deletions.
17 changes: 17 additions & 0 deletions deno_dist/bimap/implementation/context.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { RMap } from '../../collection-types/mod.ts';
import type { ArrayNonEmpty } from '../../common/mod.ts';
import { Reducer } from '../../common/mod.ts';
import { StreamSource } from '../../stream/mod.ts';
import { BiMapBuilder, BiMapEmpty, BiMapNonEmptyImpl } from '../bimap-custom.ts';
import type { BiMap } from '../internal.ts';
Expand Down Expand Up @@ -69,4 +70,20 @@ export class BiMapContext<UK, UV, Tp extends BiMap.Types = BiMap.Types>
builder = <K extends UK, V extends UV>(): BiMap.Builder<K, V> => {
return new BiMapBuilder(this as unknown as BiMapContext<K, V>);
};

reducer = <K extends UK, V extends UV>(
source?: StreamSource<readonly [K, V]>
): Reducer<readonly [K, V], BiMap<K, V>> => {
return Reducer.create(
() =>
undefined === source
? this.builder<K, V>()
: (this.from(source) as BiMap<K, V>).toBuilder(),
(builder, entry) => {
builder.addEntry(entry);
return builder;
},
(builder) => builder.build()
);
};
}
14 changes: 14 additions & 0 deletions deno_dist/bimap/interface/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type {
ArrayNonEmpty,
OmitStrong,
OptLazy,
Reducer,
RelatedTo,
ToJSON,
TraverseState,
Expand Down Expand Up @@ -496,6 +497,19 @@ export namespace BiMap {
* BiMap.builder<number, string>() // => BiMap.Builder<number, string>
*/
builder: <K extends UK, V extends UV>() => BiMap.Builder<K, V>;
/**
* Returns a `Reducer` that adds received tuples to a BiMap and returns the BiMap as a result. When a `source` is given,
* the reducer will first create a BiMap from the source, and then add tuples to it.
* @param source - (optional) an initial source of tuples to add to
* @example
* const someSource = BiMap.of([1, 'a'], [2, 'b']);
* const result = Stream.of([1, 'c'], [3, 'a']).reduce(BiMap.reducer(someSource))
* result.toArray() // => [[1, 'c'], [2, 'b'], [3, 'a']]
* @note uses a builder under the hood. If the given `source` is a BiMap in the same context, it will directly call `.toBuilder()`.
*/
reducer: <K extends UK, V extends UV>(
source?: StreamSource<readonly [K, V]>
) => Reducer<readonly [K, V], BiMap<K, V>>;
}

export interface Types extends CustomBase.KeyValue {
Expand Down
19 changes: 19 additions & 0 deletions deno_dist/bimultimap/implementation/context.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { CustomBase as CB } from '../../collection-types/mod.ts';
import type { ArrayNonEmpty } from '../../common/mod.ts';
import { Reducer } from '../../common/mod.ts';
import { StreamSource } from '../../stream/mod.ts';
import {
BiMultiMapBase,
Expand Down Expand Up @@ -107,6 +108,24 @@ export class BiMultiMapContext<
>['builder'];
};

reducer = <K extends UK, V extends UV>(
source?: StreamSource<readonly [K, V]>
): Reducer<[K, V], CB.WithKeyValue<Tp, K, V>['normal']> => {
return Reducer.create(
() =>
undefined === source
? this.builder<K, V>()
: (
this.from(source) as CB.WithKeyValue<Tp, K, V>['normal']
).toBuilder(),
(builder, entry) => {
builder.add(entry[0], entry[1]);
return builder;
},
(builder) => builder.build()
);
};

createBuilder<K extends UK, V extends UV>(
source?: CB.WithKeyValue<Tp, K, V>['nonEmpty']
): CB.WithKeyValue<Tp, K, V>['builder'] {
Expand Down
14 changes: 14 additions & 0 deletions deno_dist/bimultimap/interface/base/base.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { CustomBase as CB, RSet } from '../../../collection-types/mod.ts';
import type {
ArrayNonEmpty,
Reducer,
RelatedTo,
ToJSON,
TraverseState,
Expand Down Expand Up @@ -491,6 +492,19 @@ export namespace BiMultiMapBase {
K,
V
>['builder'];
/**
* Returns a `Reducer` that adds received tuples to a BiMultiMap and returns the BiMultiMap as a result. When a `source` is given,
* the reducer will first create a BiMultiMap from the source, and then add tuples to it.
* @param source - (optional) an initial source of tuples to add to
* @example
* const someSource = BiMultiMap.of([1, 'a'], [2, 'b']);
* const result = Stream.of([1, 'c'], [3, 'a']).reduce(BiMultiMap.reducer(someSource))
* result.toArray() // => [[1, 'a'], [1, 'c'], [2, 'b'], [3, 'a']]
* @note uses a builder under the hood. If the given `source` is a BiMultiMap in the same context, it will directly call `.toBuilder()`.
*/
reducer: <K extends UK, V extends UV>(
source?: StreamSource<readonly [K, V]>
) => Reducer<[K, V], CB.WithKeyValue<Tp, K, V>['normal']>;
}

export interface Builder<
Expand Down
34 changes: 33 additions & 1 deletion deno_dist/collection-types/map/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type {
TraverseState,
Update,
} from '../../common/mod.ts';
import { Reducer } from '../../common/mod.ts';
import { FastIterable, Stream, Streamable, StreamSource } from '../../stream/mod.ts';
import type { KeyValue, WithKeyValue } from '../custom-base.ts';

Expand Down Expand Up @@ -700,6 +701,19 @@ export namespace RMapBase {
* HashMap.builder<number, string>() // => HashMap.Builder<number, string>
*/
builder: <K extends UK, V>() => WithKeyValue<Tp, K, V>['builder'];
/**
* Returns a `Reducer` that adds received tuples to an RMap and returns the RMap as a result. When a `source` is given,
* the reducer will first create an RMap from the source, and then add tuples to it.
* @param source - (optional) an initial source of tuples to add to
* @example
* const someSource = HashMap.of([1, 'a'], [2, 'b']);
* const result = Stream.of([1, 'c'], [3, 'a']).reduce(HashMap.reducer(someSource))
* result.toArray() // => [[1, 'c'], [2, 'b'], [3, 'a']]
* @note uses a builder under the hood. If the given `source` is an RMap in the same context, it will directly call `.toBuilder()`.
*/
reducer: <K extends UK, V>(
source?: StreamSource<readonly [K, V]>
) => Reducer<readonly [K, V], WithKeyValue<Tp, K, V>['normal']>;
}

export interface Builder<K, V, Tp extends RMapBase.Types = RMapBase.Types> {
Expand Down Expand Up @@ -942,12 +956,30 @@ export namespace RMapBase {
return builder.build();
};

of = <K, V>(
of = <K extends UK, V>(
...values: ArrayNonEmpty<readonly [K, V]>
): K extends UK ? WithKeyValue<Tp, K, V>['nonEmpty'] : never => {
return this.from(values);
};

reducer = <K extends UK, V>(
source?: StreamSource<readonly [K, V]>
): Reducer<readonly [K, V], WithKeyValue<Tp, K, V>['normal']> => {
return Reducer.create(
() =>
undefined === source
? this.builder<K, V>()
: (
this.from(source) as WithKeyValue<Tp, K, V>['normal']
).toBuilder(),
(builder, entry) => {
builder.addEntry(entry);
return builder;
},
(builder) => builder.build()
);
};

mergeAllWith<R, K, O, I extends readonly [unknown, unknown, ...unknown[]]>(
fillValue: O,
mergeFun: (key: K, ...values: { [KT in keyof I]: I[KT] | O }) => R,
Expand Down
32 changes: 31 additions & 1 deletion deno_dist/collection-types/set/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
ToJSON,
TraverseState,
} from '../../common/mod.ts';
import { Reducer } from '../../common/mod.ts';
import { FastIterable, Stream, Streamable, StreamSource } from '../../stream/mod.ts';
import type { Elem, WithElem } from '../custom-base.ts';

Expand Down Expand Up @@ -343,6 +344,19 @@ export namespace RSetBase {
* HashSet.builder<number>() // => HashSet.Builder<number>
*/
builder: <T extends UT>() => WithElem<Tp, T>['builder'];
/**
* Returns a `Reducer` that appends received items to an RSet and returns the RSet as a result. When a `source` is given,
* the reducer will first create an RSet from the source, and then append elements to it.
* @param source - (optional) an initial source of elements to append to
* @example
* const someList = SortedSet.of(1, 2, 3);
* const result = Stream.range({ start: 20, amount: 5 }).reduce(SortedSet.reducer(someList))
* result.toArray() // => [1, 2, 3, 20, 21, 22, 23, 24]
* @note uses an RSet builder under the hood. If the given `source` is a RSet in the same context, it will directly call `.toBuilder()`.
*/
reducer: <T>(
source?: StreamSource<T>
) => Reducer<T, WithElem<Tp, T>['normal']>;
}

export interface Builder<T, Tp extends RSetBase.Types = RSetBase.Types> {
Expand Down Expand Up @@ -495,10 +509,26 @@ export namespace RSetBase {
return builder.build();
};

of = <T>(
of = <T extends UT>(
...values: ArrayNonEmpty<T>
): T extends UT ? WithElem<Tp, T>['nonEmpty'] : never => {
return this.from(values);
};

reducer = <T extends UT>(
source?: StreamSource<T>
): Reducer<T, WithElem<Tp, T>['normal']> => {
return Reducer.create(
() =>
undefined === source
? this.builder<T>()
: (this.from(source) as WithElem<Tp, T>['normal']).toBuilder(),
(builder, value) => {
builder.add(value);
return builder;
},
(builder) => builder.build()
);
};
}
}
15 changes: 14 additions & 1 deletion deno_dist/graph/graph/graph-base.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { RMap, RSet } from '../../collection-types/mod.ts';
import type { ArrayNonEmpty, RelatedTo } from '../../common/mod.ts';
import type { ArrayNonEmpty, Reducer, RelatedTo } from '../../common/mod.ts';
import type { Stream, Streamable, StreamSource } from '../../stream/mod.ts';
import type {
GraphConnect,
Expand Down Expand Up @@ -362,6 +362,19 @@ export namespace GraphBase {
* ArrowValuedGraphHashed.builder<number, string>() // => ArrowValuedGraphHashed.Builder<number, string>
*/
builder: <N extends UN>() => WithGraphValues<Tp, N, unknown>['builder'];
/**
* Returns a `Reducer` that adds received graph elements to a Graph and returns the Graph as a result. When a `source` is given,
* the reducer will first create a graph from the source, and then add graph elements to it.
* @param source - (optional) an initial source of graph elements to add to
* @example
* const someSource: GraphElement<number>[] = [[1, 2], [3], [5]];
* const result = Stream.of([1, 3], [4, 3]).reduce(ArrowGraphSorted.reducer(someSource))
* result.toArray() // => [[1, 2], [1, 3], [4, 3], [5]]
* @note uses a builder under the hood. If the given `source` is a Graph in the same context, it will directly call `.toBuilder()`.
*/
reducer: <N extends UN>(
source?: StreamSource.NonEmpty<GraphElement<N>>
) => Reducer<GraphElement<N>, WithGraphValues<Tp, N, unknown>['normal']>;
}

export interface Types extends VariantGraphBase.Types {
Expand Down
20 changes: 19 additions & 1 deletion deno_dist/graph/graph/impl/context.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { ArrayNonEmpty } from '../../../common/mod.ts';
import { Reducer } from '../../../common/mod.ts';
import { StreamSource } from '../../../stream/mod.ts';
import type { WithGraphValues } from '../../gen-graph-custom.ts';
import type { GraphElement } from '../../internal.ts';
import type { GraphBase } from '../graph-custom.ts';
import { GraphBuilder, GraphEmpty, GraphNonEmpty } from '../graph-custom.ts';

export interface GraphTypesContextImpl extends GraphBase.Types {
context: GraphContext<this['_N'], string, boolean, GraphTypesContextImpl>;
}
Expand Down Expand Up @@ -77,6 +77,24 @@ export class GraphContext<
return new GraphBuilder<N, Tp>(this.isDirected, this as any) as any;
};

reducer = <N extends UN>(
source?: StreamSource<GraphElement<N>>
): Reducer<GraphElement<N>, WithGraphValues<Tp, N, any>['normal']> => {
return Reducer.create(
() =>
undefined === source
? this.builder<N>()
: (
this.from(source) as WithGraphValues<Tp, N, any>['normal']
).toBuilder(),
(builder, entry) => {
builder.addGraphElement(entry);
return builder;
},
(builder) => builder.build()
);
};

createBuilder<N extends UN>(
source?: WithGraphValues<Tp, N, any>['nonEmpty']
): WithGraphValues<Tp, N, any>['builder'] {
Expand Down
19 changes: 19 additions & 0 deletions deno_dist/graph/valued-graph/impl/context.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { ArrayNonEmpty } from '../../../common/mod.ts';
import { Reducer } from '../../../common/mod.ts';
import { StreamSource } from '../../../stream/mod.ts';
import type { WithGraphValues } from '../../gen-graph-custom.ts';
import type { ValuedGraphElement } from '../../internal.ts';
Expand Down Expand Up @@ -83,6 +84,24 @@ export class ValuedGraphContext<
) as any;
};

reducer = <N extends UN, V>(
source?: StreamSource<ValuedGraphElement<N, V>>
): Reducer<ValuedGraphElement<N, V>, WithGraphValues<Tp, N, V>['normal']> => {
return Reducer.create(
() =>
undefined === source
? this.builder<N, V>()
: (
this.from(source) as WithGraphValues<Tp, N, V>['normal']
).toBuilder(),
(builder, entry) => {
builder.addGraphElement(entry);
return builder;
},
(builder) => builder.build()
);
};

createBuilder<N extends UN, V>(
source?: WithGraphValues<Tp, N, V>['nonEmpty']
): WithGraphValues<Tp, N, V>['builder'] {
Expand Down
14 changes: 14 additions & 0 deletions deno_dist/graph/valued-graph/valued-graph-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
ArrayNonEmpty,
OptLazy,
OptLazyOr,
Reducer,
RelatedTo,
SuperOf,
} from '../../common/mod.ts';
Expand Down Expand Up @@ -485,6 +486,19 @@ export namespace ValuedGraphBase {
* ArrowValuedGraphHashed.builder<number, string>() // => ArrowValuedGraphHashed.Builder<number, string>
*/
builder: <N extends UN, V>() => WithGraphValues<Tp, N, V>['builder'];
/**
* Returns a `Reducer` that adds valued received graph elements to a ValuedGraph and returns the ValuedGraph as a result. When a `source` is given,
* the reducer will first create a graph from the source, and then add graph elements to it.
* @param source - (optional) an initial source of graph elements to add to
* @example
* const someSource: ValuedGraphElement<number, string>[] = [[1, 2, 'a'], [3], [5]];
* const result = Stream.of([1, 3, 'b'], [4, 3, 'c']).reduce(ArrowGraphSorted.reducer(someSource))
* result.toArray() // => [[1, 2, 'a'], [1, 3, 'b'], [4, 3, 'c'], [5]]
* @note uses a builder under the hood. If the given `source` is a ValuedGraph in the same context, it will directly call `.toBuilder()`.
*/
reducer: <N extends UN, V>(
source?: StreamSource.NonEmpty<ValuedGraphElement<N, V>>
) => Reducer<ValuedGraphElement<N, V>, WithGraphValues<Tp, N, V>['normal']>;
}

export interface Types extends VariantValuedGraphBase.Types {
Expand Down
15 changes: 15 additions & 0 deletions deno_dist/list/context.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { RimbuError } from '../base/mod.ts';
import type { ArrayNonEmpty } from '../common/mod.ts';
import { Reducer } from '../common/mod.ts';
import { StreamSource } from '../stream/mod.ts';
import type { List } from './internal.ts';
import type {
Expand Down Expand Up @@ -120,6 +121,20 @@ export class ListContext implements List.Context {
return this.from(...sources);
};

reducer = <T>(source?: StreamSource<T>): Reducer<T, List<T>> => {
return Reducer.create(
() =>
undefined === source
? this.builder<T>()
: this.from(source).toBuilder(),
(builder, value) => {
builder.append(value);
return builder;
},
(builder) => builder.build()
);
};

leafBlock<T>(children: readonly T[]): LeafBlock<T> {
return new LeafBlock(this, children);
}
Expand Down
Loading

0 comments on commit 5eb2976

Please sign in to comment.