Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I return await in Rust?

Tags:

In JavaScript, async code is written with Promises and async/await syntax similar to that of Rust. It is generally considered redundant (and therefore discouraged) to return and await a Promise when it can simply be returned (i.e., when an async function is executed as the last thing in another function):

async function myFn() { /* ... */ }

async function myFn2() {
  // do setup work

  return await myFn()
  // ^ this is not necessary when we can just return the Promise
}

I am wondering whether a similar pattern applies in Rust. Should I prefer this:

pub async fn my_function(
    &mut self,
) -> Result<()> {
    // do synchronous setup work

    self.exec_command(
        /* ... */
    )
    .await
}

Or this:

pub fn my_function(
    &mut self,
) -> impl Future<Output = Result<()>> {
    // do synchronous setup work

    self.exec_command(
        /* ... */
    )
}

The former feels more ergonomic to me, but I suspect that the latter might be more performant. Is this the case?

like image 394
laptou Avatar asked Jan 09 '20 04:01

laptou


2 Answers

One semantic difference between the two variants is that in the first variant the synchronous setup code will run only when the returned future is awaited, while in the second variant it will run as soon as the function is called:

let fut = x.my_function();
// in the second variant, the synchronous setup has finished by now
...
let val = fut.await;  // in the first variant, it runs here

For the difference to be noticeable, the synchronous setup code must have side effects, and there needs to be a delay between calling the async function and awaiting the future it returns.

Unless you have specific reason to execute the preamble immediately, go with the async function, i.e. the first variant. It makes the function slightly more predictable, and makes it easier to add more awaits later as the function is refactored.

like image 103
user4815162342 Avatar answered Sep 19 '22 23:09

user4815162342


There is no real difference between the two since async just resolves down to impl Future<Output=Result<T, E>>. I don't believe there is any meaningful performance difference between the two, at least in my empirical usage of both.

If you are asking for preference in style then in my opinion the first one is preferred as the types are clearer to me and I agree it is more ergonomic.

like image 44
Stephen Carman Avatar answered Sep 17 '22 23:09

Stephen Carman