Почему вложенные закрытия итераторов не будут копировать значения из внешней области видимости

Я пытаюсь использовать вложенные итераторы, где внутренний итератор использует значение из внешнего итератора.

vec![0;10].iter().flat_map(|&a| {
    (0..10).map(|b|{
        a + b
    })
});

ошибка:a не живет достаточно долго

    (0..10).map(|b|{
                ^^^

примечание: ссылка должна быть действительной для вызова метода ...

Это компилируется, если я переместить внутреннее закрытие (move |b|{), но я не понимаю, зачем это нужно, учитывая, чтоa является целым числом и мог быть скопирован, а не перемещен.

 aSpex24 июл. 2016 г., 13:24
doc.rust-lang.org/book/...  В коротких замыканиях заимствует свою среду по умолчанию. Сmove это берет на себя ответственность за окружающую среду. Если значение копируемое, оно не может быть перемещено и будет скопировано.

Ответы на вопрос(1)

Решение Вопроса

И то и другоеflat_map а такжеmap ленивы Внутреннийmap не используетa сразу, но пытается «сохранить» его на случай, когда он понадобится позже, поэтому занимаетa, Но с тех порa является локальным по отношению к внешнему закрытию, и вы возвращаетесьmapВ результате, этот заем станет недействительным. Вам нужно будет использовать внутренний итератор:

vec![0;10].iter().flat_map(|&a| {
    (0..10).map(|b|{
        a + b
    }).collect::<Vec<_>>()
});

Конечно, это неэффективно, и внутреннему закрытию было бы гораздо лучше "сохранить"a, Это можно сделать, пометив внутреннюю крышку какmove:

vec![0;10].iter().flat_map(|&a| {
    (0..10).map(move |b|{
        a + b
    })
});

Обычно компилятор не позволяет вам сделать это, потому чтоflat_map закрытие не владеетaэто просто ссылка на него. Тем не менее, так как числовые типы в Rust (например,isize) реализоватьCopy черта, компилятор скопируетa вместо того, чтобы пытаться переместить его, давая желаемое поведение. Обратите внимание, что это также причина, почему вы можете разыменоватьa (с помощью|&a|) вflat_map; как правило, это потребовало бы владенияa, а не просто ссылка на него (что к чему.iter() выходы).

Ваш ответ на вопрос