export function* map(iter: IterableIterator, fn: (item: T) => U): IterableIterator { for (const item of iter) { yield fn(item); } } export function* chain(a: IterableIterator, b: IterableIterator): IterableIterator { yield* a; yield* b; } export function* zip(a: IterableIterator, b: IterableIterator): IterableIterator<[T, U]> { let itemA = a.next(); let itemB = b.next(); while (!itemA.done && !itemB.done) { yield [itemA.value, itemB.value]; itemA = a.next(); itemB = b.next(); } } export function* take(iter: IterableIterator, n: number): IterableIterator { for (const item of iter) { if (n-- === 0) { return; } yield item; } } export function skip(iter: IterableIterator, n: number): IterableIterator { while (n-- !== 0 && !iter.next().done) {} return iter; } export function reduce(iter: IterableIterator, fn: (accu: R, item: T) => R, accumulator: R): R { for (const item of iter) { accumulator = fn(accumulator, item); } return accumulator; } export function join(iter: IterableIterator<{ toString: () => string }>, glue: string): string { const first = iter.next(); if (first.done) { return ''; } let result = first.value.toString(); for (const item of iter) { result += glue + item; } return result; }