Как принять функцию asyn c в качестве аргумента? - PullRequest
2 голосов
/ 17 марта 2020

Я хотел бы повторить поведение и эргономику принятия замыкания / функции в качестве аргумента, очень похожего на map: iterator.map(|x| ...).

Я заметил, что некоторый библиотечный код позволяет передавать в асинхронном режиме c, но этот метод не позволяет мне передавать аргументы:

pub fn spawn<F, T>(future: F) -> JoinHandle<T>
where
    F: Future<Output = T> + Send + 'static,
    T: Send + 'static,
spawn(async { foo().await });

Я надеюсь выполнить одно из следующих действий:

iterator.map(async |x| {...});
async fn a(x: _) {}
iterator.map(a)

Ответы [ 2 ]

3 голосов
/ 17 марта 2020

async функции эффективно отключаются как возвращающие impl Future. Как только вы это узнаете, нужно объединить существующие методы Rust для принятия функции / замыкания, в результате чего получится функция с двумя обобщенными типами c:

use std::future::Future;

async fn example<F, Fut>(f: F)
where
    F: FnOnce(i32, i32) -> Fut,
    Fut: Future<Output = bool>,
{
    f(1, 2).await;
}

Это также можно записать как

use std::future::Future;

async fn example<Fut>(f: impl FnOnce(i32, i32) -> Fut)
where
    Fut: Future<Output = bool>,
{
    f(1, 2).await;
}
1 голос
/ 17 марта 2020

Синтаксис закрытия async |...| expr доступен на ночном канале, включая функцию async_closure.

#![feature(async_closure)]

use futures::future;
use futures::Future;
use tokio;

pub struct Bar;

impl Bar {
    pub fn map<F, T>(&self, f: F)
    where
        F: Fn(i32) -> T,
        T: Future<Output = Result<i32, i32>> + Send + 'static,
    {
        tokio::spawn(f(1));
    }
}

async fn foo(x: i32) -> Result<i32, i32> {
    println!("running foo");
    future::ok::<i32, i32>(x).await
}

#[tokio::main]
async fn main() {
    let bar = Bar;
    let x = 1;

    bar.map(foo);

    bar.map(async move |x| {
        println!("hello from async closure.");
        future::ok::<i32, i32>(x).await
    });
}

. См. 2394-async_await RF C для получения дополнительной информации

...