Клонирование строки для закрытия асинхронного перемещения в Rust

#asynchronous #rust #stream #future

#асинхронный #Ржавчина #поток #будущее

Вопрос:

Есть ли какой-либо способ, которым я могу клонировать значения для async move замыканий futures::stream ?

Я использую future for_each_concurrent

Мой код выглядит примерно так:

 async fn foo() {
    use futures::stream::{self, StreamExt};

    let a: String = String::new();

    let stream = stream::once(async { 42 });

    stream
        .for_each_concurrent(None, |stream_item| async move {
            println!("{}", a);
            println!("{}", stream_item);
        })
        .await;
}
 

Ошибка здесь:

 error[E0507]: cannot move out of `a`, a captured variable in an `FnMut` closure
  --> src/main.rs:9:61
   |
4  |       let a: String = String::new();
   |           - captured outer variable
...
9  |           .for_each_concurrent(None, |stream_item| async move {
   |  _____________________________________________________________^
10 | |             println!("{}", a);
   | |                            -
   | |                            |
   | |                            move occurs because `a` has type `String`, which does not implement the `Copy` trait
   | |                            move occurs due to use in generator
11 | |             println!("{}", stream_item);
12 | |         })
   | |_________^ move out of `a` occurs here
 

Я должен использовать move из-за этого:

 error[E0373]: async block may outlive the current function, but it borrows `stream_item`, which is owned by the current function
  --> src/main.rs:9:56
   |
9  |           .for_each_concurrent(None, |stream_item| async {
   |  ________________________________________________________^
10 | |             println!("{}", a);
11 | |             println!("{}", stream_item);
   | |                            ----------- `stream_item` is borrowed here
12 | |         })
   | |_________^ may outlive borrowed value `stream_item`
 

Если бы это был цикл, я бы просто клонировал a s на каждой итерации и перемещал эти клоны внутри замыкания, есть ли способ сделать что-то подобное здесь?

Ответ №1:

Вы можете просто клонировать a перед async move блоком:

 stream
    .for_each_concurrent(None, |stream_item| {
        let a = a.clone();
        async move {
            println!("{}", a);
            println!("{}", stream_item);
        }
    })
    .await;
 

Комментарии:

1. Действительно, спасибо!