Conversation
neurosnap
left a comment
There was a problem hiding this comment.
looks good to me! You mentioned previously that we might need to get the last item out of the iterable but I don't see a test/API for that in this PR?
|
|
||
| const EachStack = createContext<EachLoop<unknown>[]>("each"); | ||
|
|
||
| function iterate<T>(stream: Stream<T, unknown>): Operation<Iterable<T>> { |
There was a problem hiding this comment.
Can we change the iterate API to return Operation<AsyncIterable<T>> so that the consumer of each can do this
for await (const value of yield* each(stream)) {
console.log(value)
}It also removes the error-prone requirement of yield* each.next
There was a problem hiding this comment.
For implementation, we may move let current = yield* subscription.next() into the async iterator, and let [Symbol.asyncIterator]().next await for subscription.next() for each iteration.
There was a problem hiding this comment.
While, for await requires async keyword, which might be a huge pollution :(
There was a problem hiding this comment.
Yeah, I think you hit the nail on the head. One of the problems that Effection solves is it heals the scar of sync/async present in everything in JavaScript. Function vs AsyncFunction, Symbol.iterator vs Symbol.asyncIterator, Symbol.dispose vs Symbol.asyncDispose
In Effection, there is no difference between how a synchronous operation in Effection and an async one because they all boil down to a continuation. Some continuations are resumed immediately, others after some ticks of runtime, but from the correctness of the program, it is immaterial.
So unfortunately, there is no way to access the close value of an iterator or an async iterator via a for loop, so I was thinking we'd just replicate this behavior for now, and if we want to add an |
One of the design goals of Effection is to provide structured
concurrency primitives that are very aligned with ordinary JavaScript
and let libraries provide the higher abstractions based on those
primitives. This is why we have `Streams` for AsyncIterables, and
`Subscription` for `AsyncIterator`. What was missing was a natural way
to consume streams that felt like the `for await of` loop.
This introduces the `each()` and `each.next` operations that let you
consume any stream completely naturally.
```javascript
for (let value of yield* each(stream)) {
console.log(value);
yield* each.next;
}
```
2c05e70 to
6383ba6
Compare
Motivation
One of the design goals of Effection is to provide structured concurrency primitives that are very aligned with ordinary JavaScript and let libraries provide the higher abstractions based on those primitives. This is why we have
Streamsfor AsyncIterables, andSubscriptionforAsyncIterator. What was missing was a natural way to consume streams that felt like thefor await ofloop.Approach
This introduces the
each()andeach.nextoperations that let you consume any stream completely naturally.