使用“异步”谓词进行过滤时如何避免在生命周期内发生错误?

How to avoid incurring in lifetime errors while filter with an `async` predicate?

使用 async 谓词来过滤值列表会使 Rust 抱怨生命周期。即使集合是 awaited,这意味着谓词不会超过过滤值,Rust 仍然持怀疑态度。

下方完整重现playground here。请注意,它过滤我们宁愿通过引用传递的非复制结构,而不是我们可以复制并忘记而不会产生开销的简单值。

use futures::stream::iter;
use futures::StreamExt;

#[derive(Debug)]
struct Foo {
    bar: usize
}

impl Foo {
    fn new(bar: usize) -> Self {
        Self {
            bar
        }
    }
}

#[tokio::main]
async fn main() {
    let arr = vec![
      Foo::new(0),
      Foo::new(1),
      Foo::new(2)
    ];
    
    let filtered = iter(arr)
      .filter(|f| async {compute_baz(f).await > 0})
      .collect::<Vec<_>>()
      .await; 

    // should print Foo{bar:1} and Foo{bar:2}
    println!("{:?}", filtered) 
}

async fn compute_baz(foo: &Foo) -> usize {
    // ...do lengthy task...
    
    foo.bar
}

更新

正如@Ceasar 在下面指出的那样,异步函数不是 运行 并行的,可以做到吗?

我正在尝试做类似的事情:

let filter_mask = join_all(items.map(predicate)); 
let filtered = items.filter(|i| filter_mask[i]).collect::<Vec<_>>();

没有杂乱。

一个简单的解决方法是避免关闭:

let mut filtered = vec![];
for f in arr.iter() {
    if compute_baz(f).await > 0 {
        filtered.push(f);
    }
}