-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
384 additions
and
11 deletions.
There are no files selected for viewing
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
Binary file not shown.
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import { ImplSequenceBuilder } from './ImplSequenceBuilder'; | ||
import { map } from './operators'; | ||
import { scanMap } from './operators/operatorsBase'; | ||
import { builder } from './builder'; | ||
|
||
describe('Verify ImplSequenceBuilder', () => { | ||
function getBuilder() { | ||
return builder.map((a: number) => a); | ||
} | ||
|
||
test('Test empty builder', () => { | ||
const a = [1, 2, 3]; | ||
const b = new ImplSequenceBuilder(); | ||
const i = b.build(a); | ||
expect([...i]).toEqual(a); | ||
}); | ||
|
||
test('Test empty builder', () => { | ||
const a = [1, 2, 3]; | ||
const b = getBuilder(); | ||
const i = b.build(a); | ||
expect([...i]).toEqual(a); | ||
}); | ||
|
||
test('Test map', () => { | ||
const fn = (a: number) => a * 2; | ||
const a = [1, 2, 3]; | ||
const b = getBuilder().map(fn); | ||
const i = b.build(a); | ||
expect([...i]).toEqual(a.map(fn)); | ||
}); | ||
|
||
test('Test pipe', () => { | ||
const fn = (a: number) => a * 2; | ||
const a = [1, 2, 3]; | ||
const b = getBuilder().pipe(map(fn)); | ||
const i = b.build(a); | ||
expect([...i]).toEqual(a.map(fn)); | ||
}); | ||
|
||
test('Test filter', () => { | ||
const fn = (a: number) => !!(a % 2); | ||
const a = [1, 2, 3, 4]; | ||
const b = getBuilder().filter(fn); | ||
const i = b.build(a); | ||
expect([...i]).toEqual(a.filter(fn)); | ||
}); | ||
|
||
test('Test skip', () => { | ||
const a = [1, 2, 3]; | ||
const b = getBuilder().skip(2); | ||
const i = b.build(a); | ||
expect([...i]).toEqual(a.slice(2)); | ||
}); | ||
|
||
test('Test take', () => { | ||
const a = [1, 2, 3]; | ||
const b = getBuilder().take(2); | ||
const i = b.build(a); | ||
expect([...i]).toEqual(a.slice(0, 2)); | ||
}); | ||
|
||
test('Test concat', () => { | ||
const a = [1, 2, 3]; | ||
const c = [6, 7, 8]; | ||
const b = getBuilder().concat(c); | ||
const i = b.build(a); | ||
expect([...i]).toEqual(a.concat(c)); | ||
}); | ||
|
||
test('Test concatMap', () => { | ||
const fn = (a: number) => [a]; | ||
const a = [1, 2, 3]; | ||
const b = getBuilder().concatMap(fn); | ||
const i = b.build(a); | ||
expect([...i]).toEqual(a); | ||
}); | ||
|
||
test('Test scan', () => { | ||
const fn = (acc: number, cur: number) => acc + cur; | ||
const a = [1, 2, 3]; | ||
const b = getBuilder().scan(fn, 0); | ||
const i = b.build(a); | ||
expect([...i]).toEqual(a.map(scanMap(fn, 0))); | ||
}); | ||
|
||
test('Test combine', () => { | ||
const fn = (a: number, b: number | undefined) => a + (b ?? 0); | ||
const a = [1, 2, 3]; | ||
const b = getBuilder().combine(fn, a); | ||
const i = b.build(a); | ||
expect([...i]).toEqual(a.map(a => a * 2)); | ||
}); | ||
}); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { SequenceBuilder, ChainFunction, LazyIterable, Sequence } from './util/types'; | ||
import { pipe, filter, skip, take, concat, concatMap, combine, map, scan } from './operators'; | ||
import { ImplSequence } from './ImplSequence'; | ||
|
||
export class ImplSequenceBuilder<S, T = S> implements SequenceBuilder<S, T> { | ||
private operators: ChainFunction<S, T>[] = []; | ||
|
||
constructor(operators: ChainFunction<S, T>[] = []) { | ||
this.operators = operators; | ||
} | ||
|
||
build(i: LazyIterable<S>): Sequence<T> { | ||
return new ImplSequence(i).pipe(pipe.apply<unknown, any, ChainFunction<S, T>>(null, this.operators)); | ||
} | ||
|
||
pipe<U>(fn: ChainFunction<T, U>): SequenceBuilder<S, U> { | ||
return new ImplSequenceBuilder<S, U>([...this.operators, fn] as any[]); | ||
} | ||
|
||
//// Filters | ||
/** keep values where the fnFilter(t) returns true */ | ||
filter(fnFilter: (t: T) => boolean): SequenceBuilder<S, T> { | ||
return this.pipe(filter(fnFilter)); | ||
} | ||
|
||
skip(n: number): SequenceBuilder<S, T> { | ||
return this.pipe(skip(n)); | ||
} | ||
|
||
take(n: number): SequenceBuilder<S, T> { | ||
return this.pipe(take(n)); | ||
} | ||
|
||
//// Extenders | ||
concat(j: Iterable<T>): SequenceBuilder<S, T> { | ||
return this.pipe(concat(j)); | ||
} | ||
|
||
concatMap<U>(fn: (t: T) => Iterable<U>): SequenceBuilder<S, U> { | ||
return this.pipe(concatMap(fn)); | ||
} | ||
|
||
//// Mappers | ||
combine<U, V>(fn: (t: T, u?: U) => V, j: Iterable<U>): SequenceBuilder<S, V> { | ||
return this.pipe(combine(fn, j)); | ||
} | ||
|
||
/** map values from type T to type U */ | ||
map<U>(fnMap: (t: T) => U): SequenceBuilder<S, U> { | ||
return this.pipe(map(fnMap)); | ||
} | ||
|
||
scan(fnReduce: (previousValue: T, currentValue: T, currentIndex: number) => T, initialValue?: T): SequenceBuilder<S, T>; | ||
scan<U>(fnReduce: (previousValue: U, currentValue: T, currentIndex: number) => U, initialValue: U): SequenceBuilder<S, U> { | ||
return this.pipe(scan(fnReduce, initialValue)); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import { builder } from './builder'; | ||
import { map } from './operators'; | ||
import { scanMap } from './operators/operatorsBase'; | ||
// import { genSequence } from '.'; | ||
|
||
describe('Verify builder', () => { | ||
test('Test map', () => { | ||
const fn = (a: number) => a * 2; | ||
const a = [1, 2, 3]; | ||
const b = builder.map(fn); | ||
const i = b.build(a); | ||
expect([...i]).toEqual(a.map(fn)); | ||
}); | ||
|
||
test('Test pipe', () => { | ||
const fn = (a: number) => a * 2; | ||
const a = [1, 2, 3]; | ||
const b = builder.pipe(map(fn)); | ||
const i = b.build(a); | ||
expect([...i]).toEqual(a.map(fn)); | ||
}); | ||
|
||
test('Test filter', () => { | ||
const fn = (a: number) => !!(a % 2); | ||
const a = [1, 2, 3, 4]; | ||
const b = builder.filter(fn); | ||
const i = b.build(a); | ||
expect([...i]).toEqual(a.filter(fn)); | ||
}); | ||
|
||
test('Test skip', () => { | ||
const a = [1, 2, 3]; | ||
const b = builder.skip(2); | ||
const i = b.build(a); | ||
expect([...i]).toEqual(a.slice(2)); | ||
}); | ||
|
||
test('Test take', () => { | ||
const a = [1, 2, 3]; | ||
const b = builder.take(2); | ||
const i = b.build(a); | ||
expect([...i]).toEqual(a.slice(0, 2)); | ||
}); | ||
|
||
test('Test concat', () => { | ||
const a = [1, 2, 3]; | ||
const c = [6, 7, 8]; | ||
const b = builder.concat(c); | ||
const i = b.build(a); | ||
expect([...i]).toEqual(a.concat(c)); | ||
}); | ||
|
||
test('Test concatMap', () => { | ||
const fn = (a: number) => [a]; | ||
const a = [1, 2, 3]; | ||
const b = builder.concatMap(fn); | ||
const i = b.build(a); | ||
expect([...i]).toEqual(a); | ||
}); | ||
|
||
test('Test scan', () => { | ||
const fn = (acc: number, cur: number) => acc + cur; | ||
const a = [1, 2, 3]; | ||
const b = builder.scan(fn, 0); | ||
const i = b.build(a); | ||
expect([...i]).toEqual(a.map(scanMap(fn, 0))); | ||
}); | ||
|
||
test('Test combine', () => { | ||
const fn = (a: number, b: number | undefined) => a + (b ?? 0); | ||
const a = [1, 2, 3]; | ||
const b = builder.combine(fn, a); | ||
const i = b.build(a); | ||
expect([...i]).toEqual(a.map(a => a * 2)); | ||
}); | ||
}); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { ChainFunction, SequenceBuilder } from './util/types'; | ||
import { ImplSequenceBuilder } from './ImplSequenceBuilder'; | ||
import { filter, skip, take, concat, concatMap, combine, map, scan } from './operators'; | ||
|
||
|
||
function makeBuilder<T, U = T>(fn: ChainFunction<T, U>): SequenceBuilder<T, U> { | ||
return new ImplSequenceBuilder([fn]); | ||
} | ||
|
||
export const builder = Object.freeze({ | ||
pipe: <T, U>(fn: ChainFunction<T, U>) => { | ||
return makeBuilder(fn); | ||
}, | ||
|
||
//// Filters | ||
/** keep values where the fnFilter(t) returns true */ | ||
filter: <T>(fnFilter: (t: T) => boolean) => { | ||
return makeBuilder(filter(fnFilter)); | ||
}, | ||
|
||
skip: <T>(n: number) => { | ||
return makeBuilder<T>(skip(n)); | ||
}, | ||
|
||
take: <T>(n: number) => { | ||
return makeBuilder<T>(take(n)); | ||
}, | ||
|
||
//// Extenders | ||
concat: <T>(j: Iterable<T>) => { | ||
return makeBuilder(concat(j)); | ||
}, | ||
|
||
concatMap: <T, U>(fn: (t: T) => Iterable<U>) => { | ||
return makeBuilder(concatMap(fn)); | ||
}, | ||
|
||
//// Mappers | ||
combine: <T, U, V>(fn: (t: T, u?: U) => V, j: Iterable<U>) => { | ||
return makeBuilder(combine(fn, j)); | ||
}, | ||
|
||
/** map values from type T to type U */ | ||
map: <T, U>(fnMap: (t: T) => U) => { | ||
return makeBuilder(map(fnMap)); | ||
}, | ||
|
||
scan: <T, U>(fnReduce: (previousValue: U, currentValue: T, currentIndex: number) => U, initialValue: U) => { | ||
return makeBuilder(scan(fnReduce, initialValue)); | ||
}, | ||
}); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export * from './GenSequence'; | ||
export { Sequence } from './util/types'; | ||
export { Sequence, LazyIterable, IterableLike, SequenceBuilder } from './util/types'; | ||
export * from './builder'; |
Oops, something went wrong.