借入检查错误,变量在嵌套lambda中的寿命不足 [英] Borrow-check error with variable not living long enough in nested lambda

查看:66
本文介绍了借入检查错误,变量在嵌套lambda中的寿命不足的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在嵌套的lambda中遇到错误.

I am getting an error inside a nested lambda.

let rows = vec![
    vec![3, 6, 2, 8, 9, 0],
    vec![0, 0, 1, 4, 5, 1],
];

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

println!("{:?}", pair_sums);

error[E0597]: `row` does not live long enough
  --> src/main.rs:9:40
   |
9  |             (0..row.len() - 1).map(|i| row[i] + row[i + 1])
   |                                    --- ^^^ does not live long enough
   |                                    |
   |                                    capture occurs here
10 |         })
   |         - borrowed value only lives until here
11 |         .collect::<Vec<_>>();
   |                            - borrowed value needs to live until here

我可以了解为什么会发生这种情况,并且可以通过将row的值穿入内部lambda来对其进行修复:

I can sort of see why this is happening, and I can fix it by threading the value of row through to the inner lambda:

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

这太可怕了,而且不是最好的解决方案.如何在父范围中引用变量而不必显式传递变量?

This is horrible and can't be the best solution. How can I refer to variables in a parent scope without having to pass them along explicitly?

推荐答案

这里的窍门是闭包如何捕获其变量:如果闭包的内容允许,它们将引用它们,而无需查看它们的方式用于保持推断局部于闭包表达式且可预测.在这种情况下,row变量仅由引用使用,因此可以通过引用捕获.也就是说,传递给map的闭包对象包含对row的引用.因此,此对象不能离开声明row变量的作用域(即flat_map的闭包),因为该引用将指向无效的内存.返回.map(closure)将违反此规则,因为.map创建一个懒惰的迭代器来存储闭包,并且仅在请求元素时调用它.

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.

此处的解决方法是强制row变量不被引用捕获,以便闭包可以离开范围.这可以通过move关键字完成:

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<_>>();

(我的在Rust中找到闭包 post更详细地介绍了闭包,锈皮书.)

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

这篇关于借入检查错误,变量在嵌套lambda中的寿命不足的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆