В чем разница между `| _ | асинхронное перемещение {} `и` асинхронное перемещение | _ | {} `

10

Давайте рассмотрим следующие примеры:

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"

Я спрашиваю о выражении |x| async move {}вместо async move |x| {}. Последнее более очевидно, но оно приводит к ошибке компиляции:

error[E0658]: async closures are unstable

Тогда мне интересно, в чем разница между async move || {}а || async move {}. Похоже, они оба являются замыканиями для использования moveключевого слова.

$ rustc --version
rustc 1.39.0 (4560ea788 2019-11-04)
dronte7
источник

Ответы:

7

Одним из них является асинхронный блок (замыкание с асинхронным блоком в качестве его тела, если быть точным), а другим - асинхронное закрытие. За асинхронный / ожидающий RFC :

async || укупорочные

В дополнение к функциям асинхронность также может применяться к замыканиям. Как и асинхронная функция, асинхронное замыкание имеет тип возврата impl Future<Output = T>, а не T.

С другой стороны:

async блоки

Вы можете создать будущее непосредственно как выражение, используя asyncблок. Эта форма почти эквивалентна немедленному asyncзакрытию:

 async { /* body */ }

 // is equivalent to

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

кроме того, что конструкции управления потоком , как return, breakи continueне допускается в пределах тела.

moveКлючевое слово здесь , чтобы обозначить , что замыкание асинхронного и блок является собственностью захвата переменных они близки более.

И, видимо, асинхронное закрытие все еще считается нестабильным. У него есть эта проблема отслеживания .

edwardw
источник
Так что сейчас нет никакой разницы в его импорте, не так ли?
dronte7
@ dronte7 Нет, кроме того, что один нестабилен.
edwardw
они оба сразу превращаются в Будущее без каких-либо переменных окружения. разве что нестабильное асинхронное закрытие аналогично асинхронному блоку с получением внешних переменных, не так ли?
dronte7
@ dronte7 они оба возвращают Будущее при вызове. Что касается захвата переменных, они одинаковы. Вот что означает закрытие, асинхронное или нет.
Edwardw
2
Я думаю, что захват переменных довольно отличается в обоих случаях. async move || ...Переместит переменные из включающего блока в замыкание, а || async move {...}переместит переменные из замыкания в асинхронный блок. если вы хотите переместить их из включающего блока в асинхронный блок, я считаю, что вам нужно использовать move || async move {...}сейчас.
Свен Марнах