I've been thinking that it would be possible for this crate to provide an API that doesn't use proc macros at all, which has a couple of benefits:
The API could look like this:
/// async-stream ///
pub fn stream<T, F, Fut>(f: F) -> impl Stream<Item = T>
where
F: FnOnce(Yielder<T>) -> Fut,
Fut: Future<Output = ()>,
{ /* ... */ }
pub fn try_stream<T, E, F, Fut>(f: F) -> impl Stream<Item = Result<T, E>>
where
F: FnOnce(Yielder<T>) -> Fut,
Fut: Future<Output = Result<(), E>>,
{ /* ... */ }
// This macro will shadow the yielder with a function that borrows from a local.
//
// It will panic if called after the first poll or from a different stream.
#[macro_export]
macro_rules! start_stream {
// $yielder must be of type Yielder<T>
($yielder:ident) => { /* ... */ };
}
/// Usage ///
let stream = async_stream::stream(|yielder| async move {
// Must be called in the first poll, otherwise the stream will panic
start_stream!(yielder);
yielder(1).await;
yielder(2).await;
yielder(3).await;
});
I'm pretty sure this would be sound. Ergonomically, we'd lose the nice for await and yield syntax as well as the ability to use ? in regular streams (although users can always use a try_stream and then flatten the results if they want something like that), but we'd also gain the ability to specify the type of stream with turbofish syntax. I think it might be nice to support both versions in the library, depending on users' preferences. Any thoughts on the design?
I've been thinking that it would be possible for this crate to provide an API that doesn't use proc macros at all, which has a couple of benefits:
The API could look like this:
I'm pretty sure this would be sound. Ergonomically, we'd lose the nice
for awaitandyieldsyntax as well as the ability to use?in regular streams (although users can always use atry_streamand then flatten the results if they want something like that), but we'd also gain the ability to specify the type of stream with turbofish syntax. I think it might be nice to support both versions in the library, depending on users' preferences. Any thoughts on the design?