Quelle est la difference entre `| _ | déplacement asynchrone {} `et` déplacement asynchrone | _ | {} `

10

Prenons les exemples suivants:

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"

Je pose des questions sur l'expression |x| async move {}au lieu de async move |x| {}. Ce dernier est plus évident, mais il rencontre l'erreur de compilation:

error[E0658]: async closures are unstable

Ensuite, je me demande quelle est la différence entre async move || {}et || async move {}. Les deux semblent être des fermetures pour l'utilisation du movemot - clé.

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

Réponses:

7

L'un est le bloc asynchrone (une fermeture avec bloc asynchrone comme corps pour être précis), tandis que l'autre est la fermeture asynchrone. Par async / attendre RFC :

async || fermetures

En plus des fonctions, async peut également être appliqué aux fermetures. Comme une fonction asynchrone, une fermeture asynchrone a un type de retour impl Future<Output = T>plutôt que T.

D'autre part:

async blocs

Vous pouvez créer un futur directement en tant qu'expression à l'aide d'un asyncbloc. Ce formulaire est presque équivalent à une asyncfermeture immédiatement invoquée :

 async { /* body */ }

 // is equivalent to

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

sauf que les constructions de flux de contrôle comme return, breaket continuene sont pas autorisées dans le corps.

Le movemot clé ici est pour indiquer que la fermeture et le bloc asynchrones sont destinés à capturer la propriété des variables sur lesquelles ils se ferment.

Et apparemment, la fermeture asynchrone est toujours considérée comme instable. Il a ce problème de suivi .

edwardw
la source
Il n'y a donc pas de différence dans son importation en ce moment, n'est-ce pas?
dronte7
@ dronte7 non, à part le fait que l'on est instable.
edwardw
ils sont tous deux immédiatement transformés en un Futur sans ot sans acquisition de certaines variables surround. sauf que la fermeture asynchrone instable est la même chose que le bloc asynchrone avec l'acquisition de variables externes, n'est-ce pas?
dronte7
@ dronte7 ils retournent tous les deux un Futur lorsqu'ils sont appelés. En ce qui concerne la capture des variables, elles sont également les mêmes. C'est ce que signifie la fermeture, asynchrone ou non.
edwardw
2
Je pense que la capture de variables est assez différente dans les deux cas. async move || ...va déplacer les variables du bloc englobant vers la fermeture, tandis que || async move {...}va déplacer les variables de la fermeture vers le bloc asynchrone. si vous souhaitez les déplacer du bloc englobant dans le bloc asynchrone, je pense que vous devez utiliser move || async move {...}pour l'instant.
Sven Marnach