¿Cuál es la diferencia entre `| _ | movimiento asíncrono {} `y` movimiento asíncrono | _ | {} `

10

Consideremos los siguientes ejemplos:

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"

Estoy preguntando por la expresión en |x| async move {}lugar de async move |x| {}. Esto último es más obvio, pero se encuentra con el error de compilación:

error[E0658]: async closures are unstable

Entonces me pregunto cuál es la diferencia entre async move || {}y || async move {}. Ambos parecen ser cierres por usar la movepalabra clave.

$ rustc --version
rustc 1.39.0 (4560ea788 2019-11-04)
dronte7
fuente

Respuestas:

7

Uno es el bloque asíncrono (un cierre con bloque asíncrono como su cuerpo para ser precisos), mientras que el otro es el cierre asíncrono. Por asíncrono / espera RFC :

async || cierres

Además de las funciones, async también se puede aplicar a los cierres. Al igual que una función asíncrona, un cierre asíncrono tiene un tipo de retorno de impl Future<Output = T>, en lugar de T.

Por otra parte:

async bloques

Puede crear un futuro directamente como una expresión usando un asyncbloque. Este formulario es casi equivalente a un asynccierre invocado de inmediato :

 async { /* body */ }

 // is equivalent to

 (async || { /* body */ })()

excepto que las construcciones de flujo de control como return, breaky continueno están permitidos dentro del cuerpo.

La movepalabra clave aquí es denotar que el cierre y el bloqueo asíncronos son para capturar la propiedad de las variables que cierran.

Y aparentemente, el cierre asíncrono todavía se considera inestable. Tiene este problema de seguimiento .

edwardw
fuente
Entonces no hay diferencia en su importación en este momento, ¿no?
dronte7
@ dronte7 no, aparte del hecho de que uno es inestable.
edwardw
Ambos se convierten inmediatamente en un futuro sin adquirir algunas variables envolventes. excepto por ser inestable, el cierre asíncrono es lo mismo que el bloqueo asíncrono con la adquisición de variables externas, ¿no es así?
dronte7
@ dronte7 ambos devuelven un futuro cuando se les llama. En cuanto a la captura de variables, también son las mismas. Eso es lo que significa el cierre, asíncrono o no.
edwardw
2
Creo que capturar variables es bastante diferente en ambos casos. async move || ...moverá las variables del bloque de cierre al cierre, mientras || async move {...}que moverá las variables del cierre al bloque asíncrono. si desea moverlos desde el bloque que lo encierra al bloque asíncrono, creo que debe usarlo move || async move {...}por ahora.
Sven Marnach