Lifetime confusing on futures::stream::StreamExt::scan

I find it is not easy to use StreamExt methods which accept a closure returns Future(by async block).

use futures;
use async_std::task;


// failed: borrowed data cannot be stored outside of its closure
fn test_scan_futures() {
    use futures::stream::{Stream, StreamExt};
    let s = futures::stream::iter(vec![1i32, 2, 3, 4, 5]);
    let res = s.scan(3, |th, i| {
        async {
            Some(if i > *th { i } else { 0 })
        }
    }).collect::<Vec<i32>>();
    task::block_on(res);
}


// works!
fn test_scan_astd() {
    use async_std::stream::{Stream, StreamExt};
    let s = futures::stream::iter(vec![1i32, 2, 3, 4, 5]);
    let res = s.scan(3, |th, i| {
        Some(if i > *th { i } else { 0 })
    }).collect::<Vec<i32>>();
    task::block_on(res);
}

fn scan<S, B, Fut, F>(self, initial_state: S, f: F) -> Scan<Self, S, Fut, F>where F: FnMut(&mut S, Self::Item) -> Fut, Fut: Future<Output = Option<B>>,

  1. What is the lifetime of Fut?
  2. How can I borrow &mut S inside an async block?
  3. Is there someway to share data with async block?

The Fut type can't depend on the lifetime on &mut S, so no, it is not possible to borrow from the mutable reference in the async block. The unstable async closure feature will eventually fix this when it is released, but until then, you can only access th in the closure, and not in the async block.

let res = s.scan(3, |th, i| {
    let res = Some(if i > *th { i } else { 0 });
    async move { res }
}).collect::<Vec<i32>>();

The async block can share immutable data with the surrounding function.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.