Was ist der Unterschied zwischen `| _ | asynchrone Bewegung {} `und` asynchrone Bewegung | _ | {} `

10

Betrachten wir die folgenden Beispiele:

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"

Ich frage nach dem Ausdruck |x| async move {}statt async move |x| {}. Letzteres ist offensichtlicher, führt jedoch zu einem Kompilierungsfehler:

error[E0658]: async closures are unstable

Dann frage ich mich, was ist der Unterschied zwischen async move || {}und || async move {}. Beide scheinen Schließungen für die Verwendung des moveSchlüsselworts zu sein.

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

Antworten:

7

Einer ist der asynchrone Block (genauer gesagt ein Verschluss mit einem asynchronen Block als Körper), während der andere ein asynchroner Verschluss ist. Per async / warte RFC :

async || Verschlüsse

Neben Funktionen kann Async auch auf Verschlüsse angewendet werden. Wie eine asynchrone Funktion hat ein asynchroner Abschluss impl Future<Output = T>eher einen Rückgabetyp als T.

Auf der anderen Seite:

async Blöcke

Sie können eine Zukunft direkt als Ausdruck mithilfe eines asyncBlocks erstellen . Dieses Formular entspricht fast einem sofort aufgerufenen asyncAbschluss:

 async { /* body */ }

 // is equivalent to

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

außer daß Kontrollstrukturen wie return, breakund continuenicht innerhalb des Körpers erlaubt.

Das moveSchlüsselwort hier bedeutet, dass das asynchrone Schließen und Blockieren den Besitz der Variablen erfassen soll, über die sie schließen.

Und anscheinend wird die asynchrone Schließung immer noch als instabil angesehen. Es hat dieses Tracking-Problem .

edwardw
quelle
Im Moment gibt es also keinen Unterschied in der Bedeutung, nicht wahr?
dronte7
@ dronte7 nein, abgesehen davon ist man instabil.
Edwardw
Beide werden sofort zu einer Zukunft mit ot, ohne einige Surround-Variablen zu erwerben. Abgesehen davon, dass der asynchrone Abschluss instabil ist, entspricht er dem asynchronen Block beim Erfassen externer Variablen, nicht wahr?
dronte7
@ dronte7 beide geben eine Zukunft zurück, wenn sie aufgerufen werden. Die Erfassung von Variablen ist ebenfalls identisch. Dafür steht Closure, async oder nicht.
Edwardw
2
Ich denke, das Erfassen von Variablen ist in beiden Fällen sehr unterschiedlich. async move || ...Verschiebt Variablen aus dem umschließenden Block in den Abschluss, während || async move {...}Variablen aus dem Abschluss in den asynchronen Block verschoben werden. Wenn Sie sie vom umschließenden Block in den asynchronen Block verschieben möchten, müssen Sie sie vorerst verwenden move || async move {...}.
Sven Marnach