Blog Post: Futures Concurrency

https://blog.yoshuawuyts.com/futures-concurrency/

7 Likes

Nice post :slight_smile: (minor "typo": you mention a macro at the beginning but they only appear later in the post)

Aside

what an ambiguous usage of = the macro has chosen...

The idiomatic way in Rust to do this is something more akin to $ident @ $expr:

let res = select! {
    a_res @ a => a_res + 1,
    _ @ b => 0,
};

or since most futures will already be bound to identifiers, and thus using extra parens when it is not the case would not be too cumbersome, we could also imagine $tt as $ident:

let res = select! {
    a as a_res => a_res + 1,
    b as _ => 0,
};
2 Likes

I don't think that is likely to be the case for use of select!, I only have one use of it currently but it is

select! {
    packet = upstream.next() => {
        ...
    }
    packet = downstream.next() => {
        ...
    }
}

Using select! to select from multiple streams like this seems like a more common usecase to me than just selecting over bound futures (maybe with a future or two integrated as well). I do agree that maybe there could be a more readable structure though. Using = sort of reminds me of if let in some way, maybe leaning into that connotation more would make it better?

select! {
    let packet = upstream.next().await => {
        ...
    }
    let packet = downstream.next().await => {
        ...
    }
}

Yes, a let or an if let should be added at least. The one with the varname @ fut => { ... }, notation is nevertheless the one best matching the double aspect of match-branch conditional + binding the result to a new name.