"async" keyword with "for" loop using Futures 0.3


#1

I’m looking for the equivalent of futures-await's #[async] for loops.
In futures-await it looks as follows:

#[async]
for message in stream {
    // ...
}

I tried to write the equivalent using Futures 0.3 with edition=“2018”:

#![feature(futures_api, pin, async_await, await_macro, arbitrary_self_types)]

use futures::{stream, future};

async fn hello() {
    let mut my_stream = stream::once(future::ready(17));
    async for s in my_stream {
        println!("One stream element!");
    }
}

My Cargo.toml:

[package]
name = "check_async_method"
version = "0.1.0"
authors = ["real"]
edition = "2018"

[dependencies]

futures-preview = "0.3.0-alpha.7"

As a result, I get this compilation error:

$ cargo run
   Compiling check_async_method v0.1.0 (/home/real/temp/check_async_method)                                                                                                                                        
error: expected one of `move`, `|`, or `||`, found `for`                                                                                                                                                           
 --> src/main.rs:7:11                                                                                                                                                                                              
  |                                                                                                                                                                                                                
7 |     async for s in my_stream {                                                                                                                                                                                 
  |           ^^^ expected one of `move`, `|`, or `||` here                                                                                                                                                        
                                                                                                                                                                                                                   
error: aborting due to previous error                               

Which probably means that the compiler doesn’t understand the combination of the async and for keywords. I also tried omitting the async keyword, but no luck there (:

I assume that I can use the for_each combinator, but I was wondering if there is a solution similar to what I used with futures-await.

Any help is appreciated!


#2

I tried to use the for_each() combinator to overcome the lack of async for construct, and I got a different compilation problem.

This is my code:

#![feature(futures_api, pin, async_await, await_macro, arbitrary_self_types)]

use futures::{stream, future, StreamExt};

async fn hello() {
    let mut my_stream = stream::once(future::ready(17));
    my_stream.for_each(|_s| {
        let f = future::ready(18);
        let value = await!(f);
        println!("value = {}", value);
        future::ready(())
    });
}

The resulting compilation error is:

$ cargo run
   Compiling check_async_method v0.1.0 (/home/real/temp/check_async_method)                                                                                                                                        
error[E0628]: generators cannot have explicit arguments                                                                                                                                                            
 --> src/main.rs:7:24                                                                                                                                                                                              
  |                                                                                                                                                                                                                
7 |     my_stream.for_each(|_s| {                                                                                                                                                                                  
  |                        ^^^^                                

Which is similar to a problem I had at an earlier time. I solved it last time using async_block!, however, I do not know of any construct that is equivalent to it using the async keyword.


#3

For the first question, there is no syntax sugar like #[async] for provided in 0.3 (yet?). Luckily async/await’s borrowing improvements provide you with a simple alternative: while let Some(item) = await!(stream.next()) { ... }.

There is also a direct replacement for async_block! { ... }: async { ... }. Note that this is the one edition 2018 only bit of syntax currently, everything else will also work on 2015.


#4

@Nemo157: Cool!
while let Some(item) = await!(stream.next()) { ... } seems like a great solution to me.