Jaka jest różnica między `| _ | async move {} `i` async move | _ | {} `

10

Rozważmy następujące przykłady:

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"

Pytam o wyrażenie |x| async move {}zamiast async move |x| {}. To drugie jest bardziej oczywiste, ale napotyka błąd kompilacji:

error[E0658]: async closures are unstable

Zastanawiam się, jaka jest różnica między async move || {}i || async move {}. Oba wydają się być zamknięciami dla użycia movesłowa kluczowego.

$ rustc --version
rustc 1.39.0 (4560ea788 2019-11-04)
dronte7
źródło

Odpowiedzi:

6

Jednym z nich jest blok asynchroniczny (a dokładniej zamknięcie z blokiem asynchronicznym), a drugim zamknięcie asynchroniczne. Na asynchronizację / oczekiwanie na RFC :

async || domknięcia

Oprócz funkcji asynchronię można również zastosować do zamknięć. Podobnie jak funkcja asynchroniczna, zamknięcie asynchroniczne ma typ zwracany impl Future<Output = T>zamiast T.

Z drugiej strony:

async Bloki

Możesz stworzyć przyszłość bezpośrednio jako wyrażenie za pomocą async bloku. Ta forma jest prawie równoważna natychmiastowemu wywołaniu asynczamknięcia:

 async { /* body */ }

 // is equivalent to

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

z wyjątkiem tego, że konstrukcje kontroli przepływu podobne return , breaki continuenie są dozwolone w organizmie.

Słowo movekluczowe tutaj oznacza, że ​​asynchroniczne zamknięcie i blok mają przejąć własność zmiennych, które zamyka.

I najwyraźniej zamknięcie asynchroniczne jest nadal uważane za niestabilne. Ma ten problem ze śledzeniem .

edwardw
źródło
Więc nie ma teraz różnicy w jego imporcie, prawda?
dronte7
@ dronte7 nie, poza tym, że jeden jest niestabilny.
edwardw
oba natychmiast stają się Przyszłością z ot bez nabywania niektórych zmiennych surround. poza tym, że niestabilne zamknięcie asynchroniczne jest tym samym, co blok asynchroniczny z pozyskiwaniem zmiennych zewnętrznych, prawda?
dronte7,
@ dronte7 oboje zwracają Przyszłość, gdy zostaną wezwani. Jeśli chodzi o przechwytywanie zmiennych, są one również takie same. To właśnie oznacza zamknięcie, asynchronicznie lub nie.
edwardw
2
Myślę, że przechwytywanie zmiennych jest zupełnie inne w obu przypadkach. async move || ...przeniesie zmienne z otaczającego bloku do zamknięcia, natomiast || async move {...}przeniesie zmienne z zamknięcia do bloku asynchronicznego. jeśli chcesz przenieść je z bloku otaczającego do bloku asynchronicznego, myślę, że na razie musisz go użyć move || async move {...}.
Sven Marnach,