Borrow-check error with variable not living long enough in nested lambda

妖精的绣舞 提交于 2019-12-04 03:38:48
huon

The trick here is how closures capture their variables: they will take references to them if it is allowed by the contents of the closure, without looking at how they are used, to keep the inference local to the closure expression and predicable. In this case the row variable is only ever used by reference, so it is fine to be captured by reference; that is, the closure object passed to map contains a reference to row. This object hence cannot leave the scope that declares the row variable (i.e. flat_map's closure) because that reference would be left pointing to invalid memory. Returning .map(closure) will fall foul of this rule, as .map creates a lazy iterator that stores the closure and only calls it as elements are requested.

The fix here is to force the row variable to not be captured by reference, so that the closure can leave the scope. This can be done with the move keyword:

let pair_sums = rows.iter()
    .flat_map(|row| { 
        (0..row.len() - 1)
            .map(move |i| row[i] + row[i + 1])
    })
    .collect::<Vec<_>>();

In other words, the original code is equivalent to something like:

let pair_sums = rows.iter()
    .flat_map(|row: &Vec<i32>| { 
        let row_ref: &&Vec<i32> = &row;
        (0..row.len() - 1)
            .map(move |i| (*row_ref)[i] + (*row_ref)[i + 1])
    })
    .collect::<Vec<_>>();

(My Finding Closure in Rust post digs into closures in more detail, as does the Rust book.)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!