【问题标题】:Rust: Joining and iterating over futures' resultsRust:加入和迭代期货的结果
【发布时间】:2020-11-22 22:29:54
【问题描述】:

我有一些代码迭代对象,并在对结果执行某些操作之前按顺序对每个对象使用异步方法。我想更改它,以便在执行之前将异步方法调用加入一个未来。下面的重要部分位于HolderStruct::add_squares。我当前的代码如下所示:

use anyhow::Result;

struct AsyncMethodStruct {
    value: u64
}

impl AsyncMethodStruct {
    fn new(value: u64) -> Self {
        AsyncMethodStruct {
            value
        }
    }
    async fn get_square(&self) -> Result<u64> {
        Ok(self.value * self.value)
    }
}

struct HolderStruct {
    async_structs: Vec<AsyncMethodStruct>
}

impl HolderStruct {
    fn new(async_structs: Vec<AsyncMethodStruct>) -> Self {
        HolderStruct {
            async_structs
        }
    }
    async fn add_squares(&self) -> Result<u64> {
        let mut squares = Vec::with_capacity(self.async_structs.len());
        for async_struct in self.async_structs.iter() {
            squares.push(async_struct.get_square().await?);
        }
        let mut sum = 0;
        for square in squares.iter() {
            sum += square;
        }

        return Ok(sum);
    }
}

我想把HolderStruct::add_squares 改成这样:

use futures::future::join_all;
// [...]
impl HolderStruct {
    async fn add_squares(&self) -> Result<u64> {
        let mut square_futures = Vec::with_capacity(self.async_structs.len());
        for async_struct in self.async_structs.iter() {
            square_futures.push(async_struct.get_square());
        }
        let square_results = join_all(square_futures).await;
        let mut sum = 0;
        for square_result in square_results.iter() {
            sum += square_result?;
        }

        return Ok(sum);
    }
}

但是,编译器使用上面的方法给了我这个错误:

error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try`
  --> src/main.rs:46:20
   |
46 |             sum += square_result?;
   |                    ^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `&std::result::Result<u64, anyhow::Error>`
   |
   = help: the trait `std::ops::Try` is not implemented for `&std::result::Result<u64, anyhow::Error>`
   = note: required by `std::ops::Try::into_result`

如何更改代码以不出现此错误?

【问题讨论】:

    标签: asynchronous rust


    【解决方案1】:
    for square_result in square_results.iter()
    

    在此处失去iter() 呼叫。

    for square_result in square_results
    

    您似乎认为调用iter() 是遍历集合所必需的。实际上,任何实现 IntoIterator 的东西都可以在 for 循环中使用。

    Vec&lt;T&gt; 上调用 iter() 将取消对 (&amp;[T]) 的切片,并在 references 上生成一个迭代器,以指向向量元素。 ? 运算符试图从 Result 中取出值,但这只有在您拥有 Result 而不是仅仅引用它时才有可能。

    但是,如果您只是在 for 语句中使用向量本身,它将使用 IntoIterator implementation 代替 Vec&lt;T&gt;,这将产生 T 类型的项目,而不是 &amp;T

    square_results.into_iter() 做同样的事情,尽管更冗长。在函数式风格中使用迭代器时,它最有用,例如 vector.into_iter().map(|x| x + 1).collect()

    【讨论】:

      猜你喜欢
      • 2021-11-24
      • 2021-07-29
      • 1970-01-01
      • 2021-08-28
      • 2018-07-03
      • 1970-01-01
      • 1970-01-01
      • 2011-12-12
      • 2016-06-09
      相关资源
      最近更新 更多