@hongminhee/aitertools@0.6.0Built and signed on GitHub ActionsBuilt and signed on GitHub Actions
Built and signed on GitHub Actions
latest
dahlia/aitertoolsWorks with
•JSR Score88%•This package works with Cloudflare Workers, Node.js, Deno, Bun, Browsers




Downloads4/wk
•Published2 years ago (0.6.0)
Well-tested utility functions dealing with async iterables
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225/** * Makes an infinite async iterable of evenly spaced values starting with * the `start` number. * * ``` typescript * import { count } from "./infinite.ts"; * const iterable = count(5); * for await (const value of iterable) { * console.log(value); * } * ``` * * The above example will print the following and keep going forever: * * ~~~ * 5 * 6 * 7 * 8 * 9 * (...) * ~~~ * * You could adjust the interval by passing a second argument to `count()`: * * ``` typescript * import { count } from "./infinite.ts"; * const iterable = count(0, 3); * for await (const value of iterable) { * console.log(value); * } * ``` * * The above example will print the following and keep going forever: * * ~~~ * 0 * 3 * 6 * 9 * 12 * (...) * ~~~ * * As it's infinite, it's usually used with `break` to stop the iteration: * * ``` typescript * import { count } from "./infinite.ts"; * for await (const value of count(0)) { * if (value > 4) break; * console.log(value); * } * ``` * * Or with other async generators like `takeWhile()`: * * ``` typescript * import { count } from "./infinite.ts"; * import { takeWhile } from "./take.ts"; * for await (const value of takeWhile(count(0), v => v <= 4)) { * console.log(value); * } * ``` * * The both examples above will print the following 4 lines: * * ~~~ * 0 * 1 * 2 * 3 * ~~~ * * @param start The first value in the sequence. Defaults to 0. * @param step The difference between each value in the sequence. * Defaults to 1. * @returns An async iterable of evenly spaced values. */ export function count(start = 0, step = 1): AsyncIterableIterator<number> { return new Counter(start, step); } class Counter implements AsyncIterableIterator<number> { #i: number; constructor(readonly start: number, readonly step: number) { this.#i = start; } [Symbol.asyncIterator]() { return this; } next(): Promise<IteratorResult<number>> { return new Promise((resolve, _) => { const result = { done: false, value: this.#i }; this.#i += this.step; resolve(result); }); } } /** * Makes an async iterator that yields elements from the `source` and saving * a copy of each. When the `source` is exhausted, yields saved copies * indefinitely. * * Note that it may require significant memory to save the copies * depending on the length of the `source`. * * ``` typescript * import { cycle } from "./infinite.ts"; * * async function* gen() { yield 3; yield 6; yield 9; } * const iterable = cycle(gen()); * for await (const value of iterable) console.log(value); * ``` * * The above example will print the following and keep going forever: * * ~~~ * 3 * 6 * 9 * 3 * 6 * 9 * (...) * ~~~ * * @template T The type of the elements in the `source` and the returned async * iterable. * @param source An async iterable to repeat. * @returns An async iterable that repeats the `source` indefinitely. */ export async function* cycle<T>( source: Iterable<T> | AsyncIterable<T>, ): AsyncIterableIterator<T> { const cache = []; for await (const value of source) { yield value; cache.push(value); } while (cache.length > 0) { for await (const value of cache) { yield value; } } } /** * Makes an async iterator that yields the same value over and over again. * It will repeat indefinitely unless `times` is specified. * * ``` typescript * import { repeat } from "./infinite.ts"; * * const iterable = repeat("v"); * for await (const value of iterable) console.log(value); * ``` * * The above example will print the following and keep going forever: * * ~~~ * v * v * v * (...) * ~~~ * * However, if you specify the second parameter `times` it will repeat that many * times: * * ``` typescript * import { repeat } from "./infinite.ts"; * * const iterable = repeat("V", 3); * for await (const value of iterable) console.log(value); * ``` * * The above example will print the following 3 lines: * * ~~~ * V * V * V * ~~~ * * @template T The type of the `value` and the elements in the returned async * iterable. * @param value The value to repeat. * @param times The number of times to repeat. Defaults to `Infinity`. * @returns An async iterable that repeats the `value` indefinitely or * `times` times. * @throws {RangeError} when `times` is not a non-negative integer. */ export function repeat<T>( value: T, times = Infinity, ): AsyncIterableIterator<T> { if (times === Infinity) return new InfiniteRepeater(value); if (!Number.isInteger(times) || times < 0) { throw new RangeError("times must be a non-negative integer"); } return repeatDefinitely(value, times); } async function* repeatDefinitely<T>( value: T, times: number, ): AsyncIterableIterator<T> { for (let i = 0; i < times; i++) yield value; } class InfiniteRepeater<T> implements AsyncIterableIterator<T> { constructor(readonly value: T) {} [Symbol.asyncIterator]() { return this; } next(): Promise<IteratorResult<T>> { return Promise.resolve({ done: false, value: this.value }); } }