Skip to content

Commit

Permalink
chore: updated iterables (#522)
Browse files Browse the repository at this point in the history
  • Loading branch information
daomry authored Jul 20, 2023
1 parent 502f6d7 commit cba1f66
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 5 deletions.
4 changes: 4 additions & 0 deletions packages/common/src/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ function chainIter<T>(iterable: Iterable<T>): IterableChain<T> {
return {
value: iterable,
iterable,
get array() {
return [...iterable];
},
...boundToIter,
...boundToElm,
forEach: (mapping: Mapping<T, unknown>) => {
Expand Down Expand Up @@ -168,4 +171,5 @@ export type Chain<T> = {
skip: (count: number) => IterableChain<T>;
reduce: <A>(reducer: (acc: A, item: T) => A, initial: A) => ValueChain<A>;
iterable: Iterable<T>;
get array(): T[];
};
5 changes: 5 additions & 0 deletions packages/common/src/iterables-gen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export function* times(count: number, start = 0, step = 1) {
for (let i = start; i < count; i += step) {
yield i;
}
}
3 changes: 1 addition & 2 deletions packages/common/src/iterables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ export function size(iterable: Nullable<Iterable<unknown>>): number {
export function at<T>(iterable: Nullable<Iterable<T>>, index: number): T | undefined {
if (iterable) {
if (index < 0) {
const iterAsArray = Array.from(iterable);
return iterAsArray[iterAsArray.length + index];
return Array.from(iterable).at(index);
}
let i = 0;
for (const v of iterable) {
Expand Down
13 changes: 12 additions & 1 deletion packages/common/src/test/chain.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import { expect } from 'chai';
import { chain } from '../chain';
// @ts-expect-error no types
import gc from 'expose-gc/function';
import { times } from '../iterables-gen';
const forceGc = gc as () => void;

const timer = typeof performance !== 'undefined' ? performance : Date;

describe('performance', () => {
describe('chain', () => {
it('it faster than the array equivalent function for large iterables', () => {
const veryLargeArray = Array.from(new Array(2 ** 18)).map((_, i) => i % 2 ** 32);
forceGc();
Expand Down Expand Up @@ -40,4 +41,14 @@ describe('performance', () => {
expect([...result]).to.eql([...iterResult]);
expect(iterTime).to.be.lessThan(arrayTime);
});

it('can chain all of the iterable functions', () => {
expect(
chain(times(10))
.skip(2)
.map((i) => [i, 2 * i])
.flatMap((i) => i)
.filter((i) => i < 10).array
).to.eql([2, 4, 3, 6, 4, 8, 5, 6, 7, 8, 9]);
});
});
17 changes: 15 additions & 2 deletions packages/common/src/test/iterables.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,21 @@ describe('iterables', () => {
expect(isEmpty([1])).to.eql(false);
});
it(`size`, () => {
expect(size([])).to.eql(0);
expect(size([0, 1])).to.eql(2);
expect(size([]), 'size of empty array').to.eql(0);
expect(size([0, 1]), 'size of array').to.eql(2);
expect(size(undefined), 'size of undefined').to.eql(0);
expect(size(null), 'size of null').to.eql(0);
expect(size(''), 'size of empty string').to.eql(0);
expect(size('hello'), 'size of string string').to.eql(5);
expect(
size(
(function* () {
yield 1;
yield 1;
})()
),
'generated iterator'
).to.eql(2);
});
it(`map`, () => {
expect([...map([0, 1, 2], (i) => i ** 2)]).to.eql([0, 1, 4]);
Expand Down

0 comments on commit cba1f66

Please sign in to comment.