-
Notifications
You must be signed in to change notification settings - Fork 0
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
1 parent
c1223e3
commit 37676f9
Showing
7 changed files
with
159 additions
and
4 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { IteratorCollector } from "./types"; | ||
|
||
/** | ||
* Collector which converts this iterator to an array, using `Array.from`. | ||
*/ | ||
export const toArray = <TType>(): IteratorCollector<TType, TType[]> => ( | ||
input | ||
) => Array.from(input); | ||
|
||
/** | ||
* Collector which converts this iterator into a single value, much like `reduce` | ||
* @param initialValue | ||
* @param reducer | ||
*/ | ||
export const reduce = <TType, TResult>( | ||
reducer: (previousValue: TResult, value: TType) => TResult, | ||
initialValue: TResult | ||
): IteratorCollector<TType, TResult> => (input) => { | ||
let result = initialValue; | ||
for (const val of input) result = reducer(result, val); | ||
return result; | ||
}; |
This file was deleted.
Oops, something went wrong.
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 +1,8 @@ | ||
"hello world!"; | ||
export * from "./types"; | ||
export * from "./query"; | ||
|
||
export * from "./operators"; | ||
export * as operators from "./operators"; | ||
|
||
export * from "./collectors"; | ||
export * as collectors from "./collectors"; |
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,25 @@ | ||
import { IteratorOperator, IteratorSingleOperator } from "./types"; | ||
|
||
// === OPERATORS | ||
/** | ||
* Yields values from the the previous iterator after they have been passed over the given mapping function | ||
* @param mapper The mapping function | ||
*/ | ||
export const map = <TInput, TOutput>( | ||
mapper: (value: TInput) => TOutput | ||
): IteratorOperator<TInput, TOutput> => | ||
function* (input) { | ||
for (const val of input) yield mapper(val); | ||
}; | ||
|
||
// === SINGLE OPERATORS | ||
/** | ||
* Yields values from the previous iterator only if they satisfy the filter function | ||
* @param filter The filter function | ||
*/ | ||
export const filter = <TType>( | ||
filter: (value: TType) => boolean | ||
): IteratorSingleOperator<TType> => | ||
function* (input) { | ||
for (const val of input) if (filter(val)) yield val; | ||
}; |
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,24 @@ | ||
import { reduce, toArray } from "./collectors"; | ||
import { filter, map } from "./operators"; | ||
import { queryOf } from "./query"; | ||
|
||
const strings = ["foo", "bar", "baz", "foobar"]; | ||
|
||
describe("query", () => { | ||
it("pipe operators onto iterator", () => { | ||
const arr = queryOf(strings) | ||
.pipe(filter((v) => v.length === 3)) | ||
.pipe(map((v) => v.length)) | ||
.collect(toArray()); | ||
|
||
expect(arr).toEqual(expect.arrayContaining([3, 3, 3])); | ||
}); | ||
|
||
it("should collect the iterator", () => { | ||
const sl = queryOf(strings) | ||
.pipe(filter((v) => v.length === 3)) | ||
.collect(reduce((p, v) => p + v.length, 0)); | ||
|
||
expect(sl).toBeCloseTo(9); | ||
}); | ||
}); |
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 { QueryIterator, IteratorOperator, IteratorCollector } from "./types"; | ||
|
||
const queryProps: PropertyDescriptorMap = { | ||
pipe: { | ||
value( | ||
this: IterableIterator<unknown>, | ||
operator: IteratorOperator<unknown, unknown> | ||
) { | ||
return query(operator(this)); | ||
}, | ||
}, | ||
collect: { | ||
value( | ||
this: IterableIterator<unknown>, | ||
collector: IteratorCollector<unknown, unknown> | ||
) { | ||
return collector(this); | ||
}, | ||
}, | ||
}; | ||
|
||
/** | ||
* Creates a query iterator from a given iterable | ||
* @param iterable The iterable | ||
*/ | ||
export function queryOf<TType>( | ||
iterable: Iterable<TType> | ||
): QueryIterator<TType> { | ||
return query(iterable[Symbol.iterator]()); | ||
} | ||
|
||
/** | ||
* Creates a query iterator from a given iterator | ||
* @param iterator The iterator | ||
*/ | ||
export function query<TType>(iterator: Iterator<TType>): QueryIterator<TType> { | ||
// set prototype of the iterator | ||
const qi = Object.setPrototypeOf( | ||
iterator, | ||
Object.defineProperties( | ||
Object.getPrototypeOf(iterator) ?? {}, | ||
queryProps | ||
) | ||
); | ||
|
||
// make the Iterator an IterableIterator if it isn't already | ||
if (!(Symbol.iterator in qi)) | ||
Object.defineProperty(qi, Symbol.iterator, () => iterator); | ||
|
||
return qi; | ||
} |
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,29 @@ | ||
/** | ||
* A function which accepts the current iterator and returns a new one, pulling from the initial iterator as needed | ||
*/ | ||
export type IteratorOperator<TInput, TOutput> = ( | ||
iterator: IterableIterator<TInput> | ||
) => IterableIterator<TOutput>; | ||
export type IteratorSingleOperator<TType> = IteratorOperator<TType, TType>; | ||
|
||
/** | ||
* A function which collects all values from an iterator into a result | ||
*/ | ||
export type IteratorCollector<TType, TResult> = ( | ||
iterator: IterableIterator<TType> | ||
) => TResult; | ||
|
||
export interface QueryIterator<TType> extends IterableIterator<TType> { | ||
/** | ||
* Pipes this iterator over a given operator, returning the resulting iterator | ||
* @param operator The operator to map the iterator values | ||
*/ | ||
pipe<TOut>(operator: IteratorOperator<TType, TOut>): QueryIterator<TOut>; | ||
// TODO multiple operators | ||
|
||
/** | ||
* Collects all values from the iterator into a single result | ||
* @param collector The collector function | ||
*/ | ||
collect<TResult>(collector: IteratorCollector<TType, TResult>): TResult; | ||
} |