Как скопировать вместо заимствования i64 в замыкание в Rust? - PullRequest
0 голосов
/ 21 января 2019

У меня есть следующий минимальный пример моего кода:

fn main()
{
    let names : Vec<Vec<String>> = vec![
        vec!["Foo1".to_string(), "Foo2".to_string()],
        vec!["Bar1".to_string(), "Bar2".to_string()]
    ];
    let ids : Vec<i64> = vec![10, 20];

    names.iter().enumerate().flat_map(|(i,v)| {
        let id : i64 = ids[i];
        v.iter().map(|n| 
            (n.clone(), id)
        )
    });
}

Теперь, когда я компилирую это с rustc, я получаю следующее сообщение об ошибке:

error[E0597]: `id` does not live long enough
  --> main.rs:12:16
   |
11 |         v.iter().map(|n| 
   |                      --- capture occurs here
12 |             (n.clone(), id)
   |                         ^^ borrowed value does not live long enough
13 |         )
14 |     });
   |     -- borrowed value needs to live until here
   |     |
   |     borrowed value only lives until here

Но, насколько я понимаю, id относится к типу i64 и поэтому должен быть в состоянии скопировать его в захват, с тем, что именно мне нужно?

Я также пытался встроить переменную id, но безрезультатно:

error[E0597]: `i` does not live long enough
  --> main.rs:11:21
   |
10 |             v.iter().map(|n| 
   |                          --- capture occurs here
11 |                 (n.clone(), ids[i])
   |                                 ^ borrowed value does not live long enough
12 |             )
13 |         });
   |         -- borrowed value needs to live until here
   |         |
   |         borrowed value only lives until here

Так, как я могу скопировать свое целое число в замыкание вместо того, чтобы заимствовать его?

Я пытался использовать move, но rustc тоже не нравится:

error[E0507]: cannot move out of captured outer variable in an `FnMut` closure
  --> main.rs:10:17
   |
7  |         let ids : Vec<i64> = vec![10, 20];
   |             --- captured outer variable
...
10 |             v.iter().map(move |n| 
   |                          ^^^^^^^^ cannot move out of captured outer variable in an `FnMut` closure

Так что мне как-то нужно получить rustc, чтобы переместить / скопировать только одну, но не другую переменную?

Ответы [ 2 ]

0 голосов
/ 21 января 2019

Когда вы создаете замыкание в Rust, оно захватывает переменные либо по значению, либо по ссылке.Сочетание обоих невозможно.По умолчанию он захватывает по ссылке, но с ключевым словом move он захватывает по значению ( т.е. перемещает захваченные переменные внутри замыкания).

Итак, в вашем первом кодевам нужно переместиться на id внутри замыкания:

fn main() {
    let names: Vec<Vec<String>> = vec![
        vec!["Foo1".to_string(), "Foo2".to_string()],
        vec!["Bar1".to_string(), "Bar2".to_string()],
    ];
    let ids: Vec<i64> = vec![10, 20];

    names.iter().enumerate().flat_map(|(i, v)| {
        let id: i64 = ids[i];
        v.iter().map(move |n| (n.clone(), id))
    });
}

Затем вы спросите, можете ли вы "встроить" ids:

fn main() {
    let names: Vec<Vec<String>> = vec![
        vec!["Foo1".to_string(), "Foo2".to_string()],
        vec!["Bar1".to_string(), "Bar2".to_string()],
    ];
    let ids: Vec<i64> = vec![10, 20];

    names.iter().enumerate().flat_map(|(i, v)| {
        v.iter().map(|n| (n.clone(), ids[i]))
    });
}

Вы не можете поставить ids навсе в вашем внутреннем закрытии, потому что вы уже находитесь в закрытии FnMut (которое требует эксклюзивного доступа).Таким образом, вы не можете одолжить или переместить ids, потому что оно уже занято закрытием FnMut.Минимальное воспроизведение:

fn main() {
    let mut i = 0;

    let mut closure = || {
        i = 2;
        || {
            println!("i = {}", i);
        }
    };

    closure()();
}
0 голосов
/ 21 января 2019

Переместить переменную в закрытие можно с помощью ключевого слова move.Здесь вам нужно изменить замыкание как:

v.iter().map(move |n|  // move is the keyword for moving variables into closure scope.
    (n.clone(), id)
)

Детская площадка

...