Ржавчина, сделайте закрытие внутри закрытия, избегая "закрытие может пережить текущую функцию" - PullRequest
1 голос
/ 03 апреля 2020

Я пытаюсь написать функцию для преобразования структуры данных в форму:

input = [("a", [1,2,3]), ("b", [4,5,6])]

Into

output = [(a,1), (c,2) ..... (b,6)] 

Мой код в настоящее время это:

    let foo=vec![('a', vec![1,2,3]), ('v', vec![2,3,4])];
    let baz: Vec<(char,i32)> = foo.into_iter().map(|a|a.1.into_iter().map( |b|(a.0, b))).flatten().collect();
    println!("{:?}",baz);

Я получаю эту ошибку:

error[E0373]: closure may outlive the current function, but it borrows `a`, which is owned by the current function
  --> src/lib.rs:10:76
   |
10 |     let baz: Vec<(char,i32)> = foo.into_iter().map(|a|a.1.into_iter().map( |b|(a.0, b))).flatten().collect();
   |                                                                            ^^^ - `a` is borrowed here
   |                                                                            |
   |                                                                            may outlive borrowed value `a`
   |
note: closure is returned here
  --> src/lib.rs:10:55
   |
10 |     let baz: Vec<(char,i32)> = foo.into_iter().map(|a|a.1.into_iter().map( |b|(a.0, b))).flatten().collect();
   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `a` (and any other referenced variables), use the `move` keyword
   |
10 |     let baz: Vec<(char,i32)> = foo.into_iter().map(|a|a.1.into_iter().map( move |b|(a.0, b))).flatten().collect();
   |                                                                            ^^^^^^^^

error[E0382]: borrow of moved value: `a`
  --> src/lib.rs:10:76
   |
10 |     let baz: Vec<(char,i32)> = foo.into_iter().map(|a|a.1.into_iter().map( |b|(a.0, b))).flatten().collect();
   |                                                       ---                  ^^^ - borrow occurs due to use in closure
   |                                                       |                    |
   |                                                       value moved here     value borrowed here after partial move
   |
   = note: move occurs because `a.1` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait

Я думаю, это означает, что Rust не знает, как скопировать мой вектор i32s, поэтому думает, что вместо этого он должен переместить ve c, но не могу этого сделать.

Как мне исправить эту проблему? Реализуйте метод Copy для ve c, или есть более удобный способ сделать это?

Ответы [ 2 ]

4 голосов
/ 03 апреля 2020

Когда вы вызываете a.1.into_iter(), a перемещается и больше не может быть заимствован во внутреннем замыкании.

Самое простое решение - это деструктурировать a, чтобы каждый компонент мог быть заимствован. / перемещено индивидуально:

.map(|(c, v)| v.into_iter().map(move |b| (c, b)))

Также обратите внимание на ключевое слово move, которое означает, что c перемещено во внутреннее закрытие, поэтому разрешено переживать внешнее закрытие.

0 голосов
/ 03 апреля 2020

IntoIterator потребляет и возвращает значения. Поскольку Vec не реализует Copy, при вызове a.1.into_iter() он перемещается. Вы можете клонировать его следующим образом: a.1.clone().into_iter()

Кроме того, вы хотите использовать ключевое слово move, чтобы получить право владения a в закрытии.

let baz: Vec<(char, i32)> = foo
    .into_iter()
    .map(|a| a.1.clone().into_iter().map(move |b| (a.0, b)))
    .flatten()
    .collect();
println!("{:?}", baz);
// [('a', 1), ('a', 2), ('a', 3), ('v', 2), ('v', 3), ('v', 4)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...