Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between `|_| async move {}` and `async move |_| {}`

Tags:

rust

Let's consider the following examples:

main.rs

use futures::executor::block_on; use futures::future::{FutureExt, TryFutureExt};   async fn fut1() -> Result<String, u32> {   Ok("ok".to_string()) }  fn main() {     println!("Hello, world!");     match block_on(fut1().and_then(|x| async move { Ok(format!("{} is \"ok\"", x)) })) {       Ok(s) => println!("{}", s),       Err(u) => println!("{}", u)     }; }  

Cargo.toml

[dependencies] futures = "^0.3" 

I'm asking about the expression |x| async move {} instead of async move |x| {}. The latter is more obvious, but it runs into the compilation error:

error[E0658]: async closures are unstable 

Then I wonder, what is the difference between async move || {} and || async move {}. They both seems to be closures for using the move keyword.

$ rustc --version rustc 1.39.0 (4560ea788 2019-11-04) 
like image 628
dronte7 Avatar asked Dec 03 '19 11:12

dronte7


People also ask

What's the difference between future and async in Rust?

async transforms a block of code into a state machine that implements a trait called Future . Whereas calling a blocking function in a synchronous method would block the whole thread, blocked Future s will yield control of the thread, allowing other Future s to run. The value returned by async fn is a Future .

What does async move do in Rust?

async / . await are special pieces of Rust syntax that make it possible to yield control of the current thread rather than blocking, allowing other code to make progress while waiting on an operation to complete.

What is async move?

async move || ... will move variables from the enclosing block into the closure, while || async move {...} will move variables from the closure into the async block. if you want to move them from the enclosing block into the async block, I reckon you need to use move || async move {...} for now. – Sven Marnach.

Does Rust support asynchronous?

The async/await syntax is supported directly by the Rust compiler. Many utility types, macros and functions are provided by the futures crate. They can be used in any async Rust application. Execution of async code, IO and task spawning are provided by "async runtimes", such as Tokio and async-std.


1 Answers

One is the async block (a closure with async block as its body to be precise), while the other is async closure. Per async/await RFC:

async || closures

In addition to functions, async can also be applied to closures. Like an async function, an async closure has a return type of impl Future<Output = T>, rather than T.

On the other hand:

async blocks

You can create a future directly as an expression using an async block. This form is almost equivalent to an immediately-invoked async closure:

 async { /* body */ }   // is equivalent to   (async || { /* body */ })() 

except that control-flow constructs like return, break and continue are not allowed within body.

The move keyword here is to denote that the async closure and block are to capture ownership of the variables they close over.

And apparently, async closure is still deemed to be unstable. It has this tracking issue.

like image 65
edwardw Avatar answered Oct 01 '22 08:10

edwardw