import { Voidable } from "./maybe" import { Option } from "./option" import { delay as Delay } from './delay' export function flu(iter: AsyncIterable): Flu { return new Flu(() => iter) } export class Flu implements AsyncIterable { constructor(public readonly iter: () => AsyncIterable) { } [Symbol.asyncIterator](): AsyncIterator { return this.iter()[Symbol.asyncIterator]() } static empty(): Flu { return new Flu(async function* () { }) } static by(iter: () => AsyncIterable): Flu { return new Flu(iter) } static of(...iter: T[]): Flu { return flu(from(iter)) } static from(iter: Iterable): Flu { return flu(from(iter)) } static fromIter(iter: Iterable>): Flu { return flu(fromIter(iter)) } static fromCallback(): CbFlu<[T]> static fromCallback(map?: (this: This, ...args: A) => T): CbFlu static fromCallback(map?: (this: This, ...args: A) => T): CbFlu { return new CbFlu(map) } /** Create a Flu from a range starting from 0 */ static to(to: number, step: number = 1): Flu { step = Math.abs(step) if (step <= 0) step = 1 return new Flu(async function* () { for (let i = 0; i < to; i += step) { yield i } }) } /** Create a Flu from a range */ static range(from: number, to: number, step: number = 1): Flu { step = Math.abs(step) if (step <= 0) step = 1 const inc = from > to ? -step : step return new Flu(async function* () { for (let i = from; i < to; i += inc) { yield i } }) } collect(): Promise { return collect(this.iter()) } join(separator?: string): Promise { return join(this.iter(), separator) } count(): Promise { return count(this.iter()) } isEmpty(): Promise { return isEmpty(this.iter()) } first(): Promise> { return first(this.iter()) } firstO(): Promise> { return firstO(this.iter()) } last(): Promise> { return last(this.iter()) } lastO(): Promise> { return lastO(this.iter()) } nth(n: number): Promise> { return nth(this.iter(), n) } nthO(n: number): Promise> { return nthO(this.iter(), n) } stepBy(step: number): Flu { return new Flu(() => stepBy(this, step)) } chain(other: AsyncIterable | Iterable, ...more: (AsyncIterable | Iterable)[]): Flu { return new Flu(() => chain(this, other, ...more)) } zip(other: AsyncIterable): Flu<[T, U]> { return new Flu(() => zip(this, other)) } unzip(): Promise<[ (T extends [infer A, any] | readonly [infer A, any] ? A : T extends (infer R)[] ? R : unknown)[], (T extends [any, infer B] | readonly [any, infer B] ? B : T extends (infer R)[] ? R : unknown)[], ]> { return unzip(this.iter() as any) as any } map(f: (v: T) => R): Flu { return new Flu(() => map(this, f)) } mapWait(f: (v: T) => R | PromiseLike): Flu { return new Flu(() => mapWait(this, f)) } fill(v: R): Flu { return new Flu(() => fill(this, v)) } forEach(f: (v: T) => unknown | PromiseLike): Promise { return forEach(this, f) } run(): Promise { return run(this.iter()) } filter(f: (v: T) => v is S): Flu filter(f: (v: T) => unknown | PromiseLike): Flu filter(f: (v: T) => unknown | PromiseLike): Flu { return new Flu(() => filter(this, f)) } enumerate(): Flu<[T, number]> { return new Flu(() => enumerate(this)) } indexed(): Flu<[number, T]> { return new Flu(() => indexed(this)) } skip(n: number): Flu { return new Flu(() => skip(this, n)) } take(n: number): Flu { return new Flu(() => take(this, n)) } slice(from: number, to: number): Flu { return new Flu(() => slice(this, from, to)) } sub(from: number, count: number): Flu { return new Flu(() => sub(this, from, count)) } scan(init: R, f: (acc: R, val: T) => R): Flu { return new Flu(() => scan(this, init, f)) } scanWait(init: R | PromiseLike, f: (acc: R, val: T) => R | PromiseLike): Flu { return new Flu(() => scanWait(this, init, f)) } flatMap(f: (v: T) => AsyncIterable | Iterable): Flu { return new Flu(() => flatMap(this, f)) } flatten(): T extends AsyncIterable ? Flu : T extends Iterable ? Flu : never { return new Flu(() => flatten(this as any)) as any } wait(): T extends infer R | PromiseLike ? Flu : never { return new Flu(() => wait(this as any)) as any } also(f: (v: T) => unknown | PromiseLike): Flu { return new Flu(() => also(this, f)) } fold(init: R, f: (acc: R, val: T) => R): Promise { return fold(this.iter(), init, f) } foldWait(init: R | PromiseLike, f: (acc: R, val: T) => R | PromiseLike): Promise { return foldWait(this.iter(), init, f) } reduce(f: (acc: T, val: T) => T): Promise { return reduce(this.iter(), f) } reduceWait(f: (acc: T, val: T) => T | PromiseLike): Promise { return reduceWait(this.iter(), f) } all(f: (v: T) => unknown | PromiseLike): Promise { return all(this.iter(), f) } any(f: (v: T) => unknown | PromiseLike): Promise { return any(this.iter(), f) } find(f: (v: T) => unknown | PromiseLike): Promise> { return find(this.iter(), f) } position(f: (v: T) => unknown | PromiseLike): Promise { return position(this.iter(), f) } indexOf(v: T): Promise { return indexOf(this.iter(), v) } indexOfWait(v: T | PromiseLike): Promise { return indexOfWait(this.iter(), v) } max(): Promise> { return max(this.iter()) } min(): Promise> { return min(this.iter()) } merge(other: AsyncIterable): Flu { return new Flu(() => merge(this, other)) } delay(ms?: Voidable): Flu delay(f: (v: T) => unknown): Flu delay(ms: Voidable, f: (v: T) => unknown): Flu delay(a: any, b?: any): Flu { if (typeof a === 'number') return new Flu(() => delay(this, a, b)) return new Flu(() => delay(this, void 0, a)) } retry(count: number): Flu retry(f: (err: E, count: number) => unknown): Flu retry(cond: number | ((err: E, count: number) => unknown)): Flu retry(cond: number | ((err: E, count: number) => unknown) = Infinity): Flu { return new Flu(() => retry(this.iter, cond)) } timestamp(): Flu<[value: T, timestamp: number]> { return new Flu(() => timestamp(this)) } throttle(ms: number): Flu { return new Flu(() => throttle(this, ms)) } debounce(ms: number): Flu { return new Flu(() => debounce(this, ms)) } audit(ms: number): Flu { return new Flu(() => audit(this, ms)) } buffer(n: number, mode: 'count' | 'time' = 'count'): Flu { return new Flu(() => buffer(this, n, mode)) } break(): Flu { return new Flu(() => breakBy(this)) } breakBy(f: (v: T) => unknown): Flu { return new Flu(() => breakBy(this, f)) } takeIf(f: (v: T) => unknown): Flu { return new Flu(() => takeIf(this, f)) } startBy(f: (v: T) => unknown): Flu { return new Flu(() => startBy(this, f)) } skipIf(f: (v: T) => unknown): Flu { return new Flu(() => skipIf(this, f)) } drop(): Flu { return new Flu(() => drop(this)) } forEnd(): Flu { return new Flu(() => forEnd(this)) } breakAt(f: (v: T) => unknown): Flu breakAt(single: PromiseLike): Flu breakAt(single: AsyncIterable): Flu breakAt(single: AsyncIterable | PromiseLike | ((v: T) => unknown)): Flu breakAt(single: AsyncIterable | PromiseLike | ((v: T) => unknown)): Flu { if (typeof single === 'function') return this.breakBy(single) return new Flu(() => breakAt(this, single)) } takeUntil(single: PromiseLike): Flu takeUntil(single: AsyncIterable): Flu takeUntil(single: AsyncIterable | PromiseLike): Flu takeUntil(single: AsyncIterable | PromiseLike): Flu { return new Flu(() => breakAt(this, single)) } startAt(f: (v: T) => unknown): Flu startAt(single: PromiseLike): Flu startAt(single: AsyncIterable): Flu startAt(single: AsyncIterable | PromiseLike | ((v: T) => unknown)): Flu startAt(single: AsyncIterable | PromiseLike | ((v: T) => unknown)): Flu { if (typeof single === 'function') return this.startBy(single) return new Flu(() => startAt(this, single)) } skipUntil(single: PromiseLike): Flu skipUntil(single: AsyncIterable): Flu skipUntil(single: AsyncIterable | PromiseLike): Flu skipUntil(single: AsyncIterable | PromiseLike): Flu { return new Flu(() => startAt(this, single)) } push(...items: T[]): Flu { return new Flu(() => push(this, ...items)) } unshift(...items: T[]): Flu { return new Flu(() => unshift(this, ...items)) } as(): Flu { return this as any } groupBy(keyf: (v: T) => K): Flu<[K, T[]]> groupBy(keyf: (v: T) => K, valf: (v: T) => V): Flu<[K, V[]]> groupBy(keyf: (v: T) => K, valf?: (v: T) => V): Flu<[K, (T | V)[]]> { return new Flu(() => groupBy(this, keyf, valf!)) } toArray(): Promise { return toArray(this.iter()) } toSet(): Promise> { return toSet(this.iter()) } toMap(): Promise : never> { return toMap(this.iter() as any) as any } } export interface CbFlu extends Flu { cb(this: This, ...arg: A): void end(): void readonly isEnd: boolean } export class CbFlu extends Flu { constructor(map?: (this: This, ...args: A) => T) { let isEnd = false let end: (v: {}) => void const endp = new Promise<{}>(r => end = r) endp.then(() => isEnd = true) let res: Voidable<(v: { v: T }) => void> let p: Promise<{ v: T }> = new Promise((r) => res = r) function cb(v: T) { res?.({ v }); p = new Promise((r) => res = r) } async function* gen(): AsyncIterable { for (; ;) { if (isEnd) return const v = await Promise.race<{ v: T } | {}>([p, endp]) if ('v' in v) yield v.v else return } } //return [new Flu(gen), map != null ? function (this: This, ...args: A) { cb(map.call(this, ...args)) } : cb, () => (isEnd = true, end({}))] as any super(gen) Object.defineProperties(this, { cb: { value: map != null ? function (this: This, ...args: A) { cb(map.call(this, ...args)) } : cb, enumerable: true, }, end: { value: () => (isEnd = true, end({})), enumerable: true, }, isEnd: { get() { return isEnd }, enumerable: true, }, }) } } export async function* fromIter(iter: Iterable>): AsyncIterable { for (const e of iter) { yield await e } } export async function* of(...iter: T[]): AsyncIterable { for (const e of iter) { yield e } } export async function* from(iter: Iterable): AsyncIterable { for (const e of iter) { yield e } } export async function collect(iter: AsyncIterable): Promise { const r: T[] = [] for await (const e of iter) { r.push(e) } return r } export async function join(iter: AsyncIterable, separator?: string): Promise { return (await collect(iter)).join(separator) } export async function count(iter: AsyncIterable): Promise { return (await collect(iter)).length } export async function isEmpty(iter: AsyncIterable): Promise { for await (const _ of iter) return false return true } export async function first(iter: AsyncIterable): Promise> { for await (const i of iter) return i } export async function firstO(iter: AsyncIterable): Promise> { for await (const i of iter) return Option.some(i) return Option.None } export async function last(iter: AsyncIterable): Promise> { let r: Voidable for await (const i of iter) { r = i } return r } export async function lastO(iter: AsyncIterable): Promise> { let r: Voidable, has: boolean = false for await (const i of iter) { r = i has = true } return has ? Option.some(r) : Option.None } export async function nth(iter: AsyncIterable, n: number): Promise> { if (iter instanceof Array) return iter[n] let i = 0 for await (const e of iter) { if (i == n) return e i++ } return } export async function nthO(iter: AsyncIterable, n: number): Promise> { if (iter instanceof Array) return iter.length > n ? Option.some(iter[n]) : Option.None let i = 0 for await (const e of iter) { if (i == n) return Option.some(e) i++ } return Option.None } export async function* stepBy(iter: AsyncIterable, step: number): AsyncIterable { if (step < 1) step = 1 let i = 0, first = true for await (const e of iter) { if (first || i >= step) { yield e i = 1 } else { i++ } first = false } } export async function* chain(a: AsyncIterable | Iterable, b: AsyncIterable | Iterable, ...more: (AsyncIterable | Iterable)[]): AsyncIterable { yield* a yield* b for (const iter of more) { yield* iter } } export async function* zip(a: AsyncIterable, b: AsyncIterable): AsyncIterable<[A, B]> { const ai = a[Symbol.asyncIterator]() const bi = b[Symbol.asyncIterator]() for (; ;) { const a = await ai.next() if (a.done) return const b = await bi.next() if (b.done) return yield [a.value, b.value] } } export async function unzip(iter: AsyncIterable<[A, B]>): Promise<[A[], B[]]> { let [a, b]: [A[], B[]] = [[], []] for await (const i of iter) { a.push(i[0]) b.push(i[1]) } return [a, b] } export async function* map(iter: AsyncIterable, f: (v: T) => R): AsyncIterable { for await (const i of iter) { yield f(i) } } export async function* mapWait(iter: AsyncIterable, f: (v: T) => R | PromiseLike): AsyncIterable { for await (const i of iter) { yield await f(i) } } export async function* fill(iter: AsyncIterable, v: R): AsyncIterable { for await (const _ of iter) { yield v } } export async function forEach(iter: AsyncIterable, f: (v: T) => unknown | PromiseLike): Promise { for await (const i of iter) { await f(i) } } export async function run(iter: AsyncIterable): Promise { for await (const _ of iter) { } } export function filter(iter: AsyncIterable, f: (v: T) => v is S): AsyncIterable export function filter(iter: AsyncIterable, f: (v: T) => unknown): AsyncIterable export async function* filter(iter: AsyncIterable, f: (v: T) => unknown): AsyncIterable { for await (const i of iter) { if (await (f(i) as any)) yield i as any } } export async function* enumerate(iter: AsyncIterable): AsyncIterable<[T, number]> { let i = 0 for await (const e of iter) { yield [e, i] i++ } } export async function* indexed(iter: AsyncIterable): AsyncIterable<[number, T]> { let i = 0 for await (const e of iter) { yield [i, e] i++ } } export async function* skip(iter: AsyncIterable, n: number): AsyncIterable { for await (const [e, i] of enumerate(iter)) { if (i >= n) yield e } } export async function* take(iter: AsyncIterable, n: number): AsyncIterable { for await (const [e, i] of enumerate(iter)) { yield e if (i + 1 >= n) return } } export async function* slice(iter: AsyncIterable, from: number, to: number): AsyncIterable { for await (const [e, i] of enumerate(iter)) { if (i >= from) yield e if (i + 1 >= to) return } } export function sub(iter: AsyncIterable, from: number, count: number): AsyncIterable { return slice(iter, from, count + from) } export async function* scan(iter: AsyncIterable, init: R, f: (acc: R, val: T) => R): AsyncIterable { let acc = init for await (const i of iter) { acc = f(acc, i) yield acc } } export async function* scanWait(iter: AsyncIterable, init: R | PromiseLike, f: (acc: R, val: T) => R | PromiseLike): AsyncIterable { let acc = await init for await (const i of iter) { acc = await f(acc, i) yield acc } } export async function* flatMap(iter: AsyncIterable, f: (v: T) => AsyncIterable | Iterable): AsyncIterable { for await (const i of iter) { yield* f(i) } } export async function* flatten(iter: AsyncIterable | Iterable>): AsyncIterable { for await (const i of iter) { yield* i } } export async function* wait(iter: AsyncIterable>): AsyncIterable { for await (const i of iter) { yield await i } } export async function* also(iter: AsyncIterable, f: (v: T) => unknown | PromiseLike): AsyncIterable { for await (const i of iter) { await f(i) yield i } } export async function fold(a: AsyncIterable, init: R, f: (acc: R, val: T) => R): Promise { let acc = init for await (const i of a) { acc = f(acc, i) } return acc } export async function foldWait(a: AsyncIterable, init: R | PromiseLike, f: (acc: R, val: T) => R | PromiseLike): Promise { let acc = await init for await (const i of a) { acc = await f(acc, i) } return acc } export async function reduce(a: AsyncIterable, f: (acc: T, val: T) => T): Promise { let acc: T | undefined, first = true for await (const i of a) { if (first) (acc = i, first = false) else acc = f(acc!, i) } if (first) throw new TypeError('no item') return acc! } export async function reduceWait(a: AsyncIterable, f: (acc: T, val: T) => T | PromiseLike): Promise { let acc: T | undefined, first = true for await (const i of a) { if (first) (acc = i, first = false) else acc = await f(acc!, i) } if (first) throw new TypeError('no item') return acc! } export async function all(a: AsyncIterable, f: (v: T) => unknown | PromiseLike): Promise { for await (const i of a) { if (!await f(i)) return false } return true } export async function any(a: AsyncIterable, f: (v: T) => unknown | PromiseLike): Promise { for await (const i of a) { if (await f(i)) return true } return false } export async function find(a: AsyncIterable, f: (v: T) => unknown | PromiseLike): Promise> { for await (const i of a) { if (await f(i)) return i } } export async function position(a: AsyncIterable, f: (v: T) => unknown | PromiseLike): Promise { for await (const [e, i] of enumerate(a)) { if (await f(e)) return i } return -1 } export async function indexOf(a: AsyncIterable, v: T): Promise { for await (const [e, i] of enumerate(a)) { if (e == v) return i } return -1 } export async function indexOfWait(a: AsyncIterable, v: T | PromiseLike): Promise { const vV = await v for await (const [e, i] of enumerate(a)) { if (e == vV) return i } return -1 } export async function max(a: AsyncIterable): Promise> { let r: Voidable, first = true for await (const i of a) { if (first) (r = i, first = false) else if (i > r!) r = i } return r } export async function min(a: AsyncIterable): Promise> { let r: Voidable, first = true for await (const i of a) { if (first) (r = i, first = false) else if (i < r!) r = i } return r } async function* Continue(n: Promise>, iter: AsyncIterator): AsyncIterable { for (; ;) { const r = await n if (r.done) return yield r.value n = iter.next() } } export async function* merge(a: AsyncIterable, b: AsyncIterable): AsyncIterable { const ai = a[Symbol.asyncIterator]() const bi = b[Symbol.asyncIterator]() let an = ai.next() let bn = bi.next() for (; ;) { const r = await Promise.race([an.then(a => ({ a })), bn.then(b => ({ b }))]) if ('a' in r) { if (r.a.done) return yield* Continue(bn, bi) yield r.a.value an = ai.next() } else { if (r.b.done) return yield* Continue(an, ai) yield r.b.value bn = bi.next() } } } export async function* delay(iter: AsyncIterable, ms?: Voidable, f?: (v: T) => unknown): AsyncIterable { if (f != null) { for await (const e of iter) { if (f(e)) await Delay(ms) yield e } } else { for await (const e of iter) { await Delay(ms) yield e } } } export async function* retry(iterFn: () => AsyncIterable, count: number | ((err: E, count: number) => unknown) = Infinity): AsyncIterable { if (typeof count === 'function') { let i = 0 for (; ;) { const iter = iterFn() try { for await (const e of iter) { yield e } return } catch (e) { i++ if (count(e, i)) continue throw e } } } else { for (; ;) { const iter = iterFn() try { for await (const e of iter) { yield e } return } catch (e) { count-- if (count > 0) continue throw e } } } } export async function* timestamp(iter: AsyncIterable): AsyncIterable<[value: T, timestamp: number]> { for await (const e of iter) { yield [e, +new Date] } } export async function* throttle(iter: AsyncIterable, ms: number = 300): AsyncIterable { let last = +new Date for await (const e of iter) { const now = +new Date if (last + ms <= now) { yield e last = now } } } export async function* debounce(iter: AsyncIterable, ms: number = 300): AsyncIterable { let timeout: any, res: (v: { v: T }) => void, end: (v: {}) => void, endp = new Promise<{}>(r => end = r) queueMicrotask(async () => { for await (const v of iter) { if (timeout) clearTimeout(timeout) timeout = setTimeout(() => res?.({ v }), ms) } end({}) }) for (; ;) { const v = await Promise.race<{ v: T } | {}>([new Promise<{ v: T }>(r => res = r), endp]) if ('v' in v) yield v.v else return } } export async function* audit(iter: AsyncIterable, ms: number = 300): AsyncIterable { let e: T, first = true, end: (v: {}) => void, endp = new Promise<{}>(r => end = r) queueMicrotask(async () => { for await (const v of iter) { e = v first = false } end({}) }) let timeout for (; ;) { const v = await Promise.race<{ v: T } | {}>([new Promise<{ v: T }>(res => timeout = setTimeout(() => res({ v: e }), ms)), endp]) clearTimeout(timeout) if ('v' in v) { if (first) continue yield v.v } else return } } export async function* buffer(iter: AsyncIterable, n: number, mode: 'count' | 'time' = 'count'): AsyncIterable { if (n <= 0) { for await (const e of iter) yield [e] } else if (mode == 'count') { let buffer: T[] = [] for await (const e of iter) { buffer.push(e) if (buffer.length >= n) yield buffer buffer = [] } if (buffer.length != 0) yield buffer } else { let buffer: T[] = [], first = true, end: (v: {}) => void, endp = new Promise<{}>(r => end = r) queueMicrotask(async () => { for await (const v of iter) { buffer.push(v) first = false } end({}) }) let timeout for (; ;) { const v = await Promise.race<{ v: T[] } | {}>([new Promise<{ v: T[] }>(res => timeout = setTimeout(() => (res({ v: buffer }), buffer = []), n)), endp]) clearTimeout(timeout) if ('v' in v) { if (first) continue yield v.v } else { if (buffer.length != 0) yield buffer return } } } } export async function* breakBy(iter: AsyncIterable, f?: (v: T) => unknown): AsyncIterable { if (f == null) return for await (const e of iter) { if (f(e)) return } } export async function* takeIf(iter: AsyncIterable, f?: (v: T) => unknown): AsyncIterable { if (f == null) return for await (const e of iter) { if (!f(e)) return } } export async function* skipIf(iter: AsyncIterable, f: (v: T) => unknown): AsyncIterable { const it = iter[Symbol.asyncIterator]() let p = it.next() for (; ;) { const r = await p if (r.done) return if (!f(r.value)) return yield* Continue(p, it) p = it.next() } } export async function* startBy(iter: AsyncIterable, f: (v: T) => unknown): AsyncIterable { const it = iter[Symbol.asyncIterator]() let p = it.next() for (; ;) { const r = await p if (r.done) return if (f(r.value)) return yield* Continue(p, it) p = it.next() } } export async function* drop(iter: AsyncIterable): AsyncIterable { for await (const _ of iter) { yield } } export async function* forEnd(iter: AsyncIterable): AsyncIterable { for await (const _ of iter) { } } export async function* breakAt(iter: AsyncIterable, single: AsyncIterable | PromiseLike): AsyncIterable { if (Symbol.asyncIterator in single) { single = first(single as AsyncIterable) } const endp = new Promise<{}>(async r => { await single r({}) }) const it = iter[Symbol.asyncIterator]() let p = it.next().then(v => ({ v })) for (; ;) { const r = await Promise.race<{ v: IteratorResult } | {}>([p, endp]) if ('v' in r) { if (r.v.done) return yield r.v.value p = it.next().then(v => ({ v })) } else return } } export async function* startAt(iter: AsyncIterable, single: AsyncIterable | PromiseLike): AsyncIterable { if (Symbol.asyncIterator in single) { single = first(single as AsyncIterable) } const endp = new Promise<{}>(async r => { await single r({}) }) const it = iter[Symbol.asyncIterator]() let p = it.next() for (; ;) { const r = await Promise.race<{ v: IteratorResult } | {}>([p.then(v => ({ v })), endp]) if ('v' in r) { if (r.v.done) return p = it.next() } else return yield* Continue(p, it) } } export async function* push(a: AsyncIterable, ...items: T[]): AsyncIterable { yield* a yield* items } export async function* unshift(a: AsyncIterable, ...items: T[]): AsyncIterable { yield* items yield* a } export function as(a: AsyncIterable): AsyncIterable { return a as any } export function groupBy(a: AsyncIterable, keyf: (v: T) => K): AsyncIterable<[K, T[]]> export function groupBy(a: AsyncIterable, keyf: (v: T) => K, valf: (v: T) => V): AsyncIterable<[K, V[]]> export async function* groupBy(a: AsyncIterable, keyf: (v: T) => K, valf?: (v: T) => V): AsyncIterable<[K, (V | T)[]]> { const groups = new Map() for await (const e of a) { const key = keyf(e) const val = valf?.(e) ?? e let group = groups.get(key) if (group == null) groups.set(key, group = []) group.push(val) } yield* groups } export async function toArray(a: AsyncIterable): Promise { return collect(a) } export async function toSet(a: AsyncIterable): Promise> { const r = new Set() for await (const e of a) { r.add(e) } return r } export async function toMap(a: AsyncIterable<[K, V]>): Promise> { const r = new Map() for await (const [k, v] of a) { r.set(k, v) } return r }