rust 在闭包中传递一个异步函数,返回Result,其中< T>review:: www.example.com 接受

oalqel3c  于 2023-04-30  发布在  其他
关注(0)|答案(1)|浏览(88)

我有这些异步函数,add_two_numcheck_num

use anyhow::{Error, Result, Ok};
use rayon::prelude::*;

pub async fn add_two_num(num_one: u64, num_two: u64) -> Result<u64> {
    check_num(num_one).await?; // calls another async function that returns a anyhow::Result<T>, where `T` is a different `T` from the return of the `add_two_num` function
    check_num(num_two).await?;
    anyhow::Ok(num_one + num_two)
}

pub async fn check_num(num: u64) -> Result<()> {
    assert!(num <= u64::MAX);
    Ok(())
}

这些函数只是人为的函数,重点是使返回类型anyhow::Result<T>,其中Tadd_two_num中的不同调用位置是不同的,e。例如,check_sum调用两次,每次返回anyhow::Result<()>T = ())。

#[tokio::main]
async fn main() -> Result<()> {
    let nums_one: Vec<u64> = vec![1, 2, 3, 4, 5, 6, 7];
    let nums_two: Vec<u64> = vec![1, 2, 3, 4, 5, 6, 7];

    let results = nums_one.into_par_iter()
    .zip_eq(nums_two.into_par_iter())
    .map(async move |(num_one, num_two)| {
        add_two_num(num_one, num_two).await?
        // questions: 1. how to write this closure to be passed into `.map()`?
        // 2. the `?` operator will early return the error, how to indicate this into the signature of the closure or basically, how to 'iterate' over the Result<T>?
    }).collect::<Vec<_>>();

    Ok(())
}

我正在尝试做的是:
1.压缩IntoParallelIterator,将它们发送到闭包中。
1.闭包调用闭包中的异步函数,异步函数使用?运算符提前返回anyhow::Error
问题:
1.如何编写闭包来调用闭包中的异步函数?
1.如何写闭包的签名来表明它返回一个anyhow::Result<T>

gstyhher

gstyhher1#

你不能很容易地从Rayon的回调中调用异步函数。但由于你已经在使用async,你可以完全避免使用Rayon,并为你的操作生成异步任务(并行运行):

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let nums_one: Vec<u64> = vec![1, 2, 3, 4, 5, 6, 7];
    let nums_two: Vec<u64> = vec![1, 2, 3, 4, 5, 6, 7];

    let tasks = nums_one
        .into_iter()
        .zip_eq(nums_two)
        .map(|(num_one, num_two)| {
            tokio::spawn(async move {
                let result = add_two_num(num_one, num_two).await?;
                Ok::<_, anyhow::Error>(result)
            })
        })
        .collect_vec();
    let v: Vec<u64> = future::join_all(tasks)
        .await
        .into_iter()
        // this unwrap triggers only in case of panic
        .map(|result| result.unwrap())
        .collect::<Result<_, _>>()?;
    assert_eq!(v, [2, 4, 6, 8, 10, 12, 14]);
    Ok(())
}

Playground

相关问题