Sync iterables and [[asyncIterator]]

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Sync iterables and [[asyncIterator]]

Herby Vojčík
Hello!


Lately, I created this in one project:

export async function* zip (...iterables) {
     for (const iterators = iterables.map(each => (each[Symbol.iterator]
|| each[Symbol.asyncIterator]).apply(each)); ;) {
         const all = await Promise.all(iterators.map(async each => await
each.next()));
         if (all.some(each => each.done)) break;
         yield all.map(each => each.value);
     }
}

It was sync generator before, but once one of the entries became async
generator, I changed the zip itself to be async.

My question is to the pretty ugly

   const iterators = iterables.map(each => (each[Symbol.iterator] ||
each[Symbol.asyncIterator]).apply(each))

Is there some more idiomatic way to find "any iterator; sync or async" /
alternatively, could sync iterator return respective [[asyncIterator]]
as well, just promisifying the result (as a sort of proto-proposal of sort)?

Or is there some easy way to change sync iterable to async iterable, so
I could change the other ones at call site?


Thanks, Herby
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Sync iterables and [[asyncIterator]]

Isiah Meadows-2
There isn't currently a means to trivially convert them, but sync iterables can still be used in `for await`. They're implicitly wrapped into an async iterable\*, and then used that way.

\* That's supposed to be a spec implementation detail, but was accidentally exposed at one point. I recall reading about it somewhere, but I can't easily find it.

On Sun, Aug 19, 2018 at 14:38 Herbert Vojčík <[hidden email]> wrote:
Hello!


Lately, I created this in one project:

export async function* zip (...iterables) {
     for (const iterators = iterables.map(each => (each[Symbol.iterator]
|| each[Symbol.asyncIterator]).apply(each)); ;) {
         const all = await Promise.all(iterators.map(async each => await
each.next()));
         if (all.some(each => each.done)) break;
         yield all.map(each => each.value);
     }
}

It was sync generator before, but once one of the entries became async
generator, I changed the zip itself to be async.

My question is to the pretty ugly

   const iterators = iterables.map(each => (each[Symbol.iterator] ||
each[Symbol.asyncIterator]).apply(each))

Is there some more idiomatic way to find "any iterator; sync or async" /
alternatively, could sync iterator return respective [[asyncIterator]]
as well, just promisifying the result (as a sort of proto-proposal of sort)?

Or is there some easy way to change sync iterable to async iterable, so
I could change the other ones at call site?


Thanks, Herby
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Sync iterables and [[asyncIterator]]

Gus Caplan
In reply to this post by Herby Vojčík
If you use for-await syntax, the js implementation will internally use GetIterator[1] which will look for Symbol.asyncIterator and if it can't find it it will return an async wrapper around Symbol.iterator

-Gus



---- On Sun, 19 Aug 2018 16:34:27 -0500 Herbert Vojčík <[hidden email]> wrote ----

Hello!


Lately, I created this in one project:

export async function* zip (...iterables) {
for (const iterators = iterables.map(each => (each[Symbol.iterator]
|| each[Symbol.asyncIterator]).apply(each)); ;) {
const all = await Promise.all(iterators.map(async each => await
each.next()));
if (all.some(each => each.done)) break;
yield all.map(each => each.value);
}
}

It was sync generator before, but once one of the entries became async
generator, I changed the zip itself to be async.

My question is to the pretty ugly

const iterators = iterables.map(each => (each[Symbol.iterator] ||
each[Symbol.asyncIterator]).apply(each))

Is there some more idiomatic way to find "any iterator; sync or async" /
alternatively, could sync iterator return respective [[asyncIterator]]
as well, just promisifying the result (as a sort of proto-proposal of sort)?

Or is there some easy way to change sync iterable to async iterable, so
I could change the other ones at call site?


Thanks, Herby
_______________________________________________
es-discuss mailing list



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Sync iterables and [[asyncIterator]]

Herby Vojčík


On August 20, 2018 1:46:45 AM GMT+02:00, Gus Caplan <[hidden email]> wrote:
>If you use for-await syntax, the js implementation will internally use
>GetIterator[1] which will look for Symbol.asyncIterator and if it can't
>find it it will return an async wrapper around Symbol.iterator -Gus

Would be nice to have something like Reflect.getAsyncIteratorOf(...), then. Or AsyncIterator.of(...), if something like AsyncIterator exists.
That would do the wrapping of sync ones as well.

>[1]: https://tc39.github.io/ecma262/#sec-getiterator ---- On Sun, 19
>Aug 2018 16:34:27 -0500 Herbert Vojčík <[hidden email]> wrote ----
>Hello! Lately, I created this in one project: export async function*
>zip (...iterables) { for (const iterators = iterables.map(each =>
>(each[Symbol.iterator] || each[Symbol.asyncIterator]).apply(each)); ;)
>{ const all = await Promise.all(iterators.map(async each => await
>each.next())); if (all.some(each => each.done)) break; yield
>all.map(each => each.value); } } It was sync generator before, but once
>one of the entries became async generator, I changed the zip itself to
>be async. My question is to the pretty ugly const iterators =
>iterables.map(each => (each[Symbol.iterator] ||
>each[Symbol.asyncIterator]).apply(each)) Is there some more idiomatic
>way to find "any iterator; sync or async" / alternatively, could sync
>iterator return respective [[asyncIterator]] as well, just promisifying
>the result (as a sort of proto-proposal of sort)? Or is there some easy
>way to change sync iterable to async iterable, so I could change the
>other ones at call site? Thanks, Herby
>_______________________________________________ es-discuss mailing list
>[hidden email] https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss