Seeker
Seeker

Reputation: 115

Rust: Async find (use await within predicate)

I am trying to use async within find predicates. We can use the find method to look up an element within an iterator as follows:

let element = some_elements.iter().find(|element| {
  // some_async_method(element).await;
  // true or false based on some logic
});

In my case, I need to call async methods as a part of my lookup logic. However, when I use await, I end up with the error that await cannot be called within non-async block, which is expected. When I try to make my function async as follows:

let element = some_elements.iter().find(|element| async move{
  // some_async_method(element).await;
  // true or false based on some logic
});

I get the error: expected bool, found opaque type

I tried to to use rayon, but could not find an example for what I am looking for.

Upvotes: 3

Views: 513

Answers (1)

cafce25
cafce25

Reputation: 27532

You can use futures::stream::iter to turn your iterator into a Stream.

Since find is not implemented on StreamExt I replaced it with filter().next() in the following:

use futures::stream::StreamExt;
//…
let element = futures::stream::iter(&some_elements)
    .filter(|e| Box::pin(async move { predicate(e).await }))
    .next()
    .await;

If you actually want to do your work asynchronously though you'd have to be a little more verbose and collect into a FuturesOrdered/FuturesUnordered depending on your actual requirements:

let element = some_elements
    .iter()
    .map(|&e| async move { (predicate(e).await, e) })
    .collect::<FuturesUnordered<_>>()
    .filter_map(|(p, e)| Box::pin(async move { p.then_some(e) }))
    .next()
    .await;

Upvotes: 2

Related Questions