itiriri-async icon indicating copy to clipboard operation
itiriri-async copied to clipboard

map an asynchronous function?

Open tsani opened this issue 4 years ago • 2 comments

The type of .map() is

(selector: (x: T) => S): AsyncIterableQuery<S>

but I would have expected

(selector: (x: T) => Promise<S>): AsyncIterableQuery<S>

allowing the transformation of each element to be asynchronous.

Maybe there's a way to pull this off using .flat() but I can't seem to make it work. Any ideas?

tsani avatar Mar 01 '21 18:03 tsani

Quick update: I did find a workaround with .flat() but it's kinda gnarly.

seq.flat(async function* (x) { yield await f(x) })

Surely seq.map(f) would be way nicer.

And this workaround is especially unpleasant if f needs to access this, as one can't use an arrow function to create a generator.

EDIT: and unfortunately, the overload for .flat() that takes a transformation returns a plain AsyncIterable and not an AsyncIterableQuery, so I can't continue to chain itiriri methods together after using the workaround without wrapping up with itiririAsync again.

tsani avatar Mar 01 '21 18:03 tsani

Hi @tsani,
I don't remember the exact implementation, but from the source code here it looks like map accepts async functions as well.

So in the case of:

(selector: (x: T) => S): AsyncIterableQuery<S>

the selector can be a function that returns a Promise. I agree typings have to be fixed.
It should look like:

(selector: (x: T) => S | Promise<S>): AsyncIterableQuery<S>

You're welcome to open a PR.

dimadeveatii avatar Mar 12 '21 16:03 dimadeveatii