Qual é a diferença entre `| _ | movimento assíncrono {} `e` movimento assíncrono | _ | {} `

10

Vamos considerar os seguintes exemplos:

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"

Estou perguntando sobre a expressão em |x| async move {}vez de async move |x| {}. O último é mais óbvio, mas ocorre o erro de compilação:

error[E0658]: async closures are unstable

Então eu me pergunto, qual é a diferença entre async move || {}e || async move {}. Ambos parecem ser fechamentos para usar a movepalavra - chave.

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

Respostas:

7

Um é o bloqueio assíncrono (um fechamento com o bloco assíncrono como seu corpo para ser mais preciso), enquanto o outro é o fechamento assíncrono. Por RFC assíncrono / aguardado :

async || fechamentos

Além das funções, o assíncrono também pode ser aplicado aos fechamentos. Como uma função assíncrona, um fechamento assíncrono tem um tipo de retorno impl Future<Output = T>, em vez de T.

Por outro lado:

async blocos

Você pode criar um futuro diretamente como uma expressão usando um asyncbloco. Este formulário é quase equivalente a um asyncfechamento invocado imediatamente :

 async { /* body */ }

 // is equivalent to

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

excepto que construções de controlo de fluxo como o return, breake continuenão são permitidas no interior do corpo.

A movepalavra-chave aqui é denotar que o fechamento e o bloco assíncrono devem capturar a propriedade das variáveis ​​que eles fecham.

E, aparentemente, o fechamento assíncrono ainda é considerado instável. Ele tem esse problema de rastreamento .

edwardw
fonte
Portanto, não há diferença em sua importação no momento, não é?
precisa
@ dronte7 não, além do fato de que um é instável.
Edwardw 4/12/19
ambos são imediatamente transformados em um futuro com ot sem adquirir algumas variáveis ​​surround. exceto pelo fato de o fechamento assíncrono instável ser o mesmo do bloco assíncrono com a aquisição de variáveis ​​externas, não é?
dronte7
@ dronte7 ambos retornam um futuro quando são chamados. Quanto à captura de variáveis, elas também são as mesmas. Isso é o que significa fechamento, assíncrono ou não.
Edwardw 4/12/19
2
Eu acho que capturar variáveis ​​é bem diferente nos dois casos. async move || ...moverá variáveis ​​do bloco anexo para o fechamento, enquanto || async move {...}moverá variáveis ​​do fechamento para o bloco assíncrono. se você deseja movê-los do bloco anexo para o bloco assíncrono, acho que você precisa usá-lo move || async move {...}por enquanto.
Sven Marnach