在嵌套迭代器中指定生命周期以进行展平

时间:2016-12-23 22:35:46

标签: iterator rust nested-loops lifetime

我正在编写一个函数,该函数应该采用几个向量并将它们的笛卡尔积(它们的所有对组合)生成为行主要顺序的向量。换句话说,如果我有

JObject.Parse

我想制作

let x_coords = vec![1, 2, 3];
let y_coords = vec![4, 5, 6];

对于vec![ [1,4], [1,5], [1,6], [2,4], [2,5], [2,6], [3,4], [3,5], [3,6] ] 来说,这似乎是一个完美的工作:

.flat_map()

但这不起作用,因为fn main() { let x_coords = vec![1, 2, 3]; let y_coords = vec![4, 5, 6]; let coord_vec: Vec<[isize; 2]> = x_coords.iter().map(|&x_coord| { y_coords.iter().map(|&y_coord| { [x_coord, y_coord] }) }).flat_map(|s| s).collect(); // Expecting to get: vec![ [1,4], [1,5], [1,6], [2,4], [2,5], [2,6], [3,4], [3,5], [3,6] ] println!("{:?}", &coord_vec); } 的寿命不够长。根据编译器,它最终在&x_coord地图内部,然后永远不会退回。

我尝试在闭包中使用y_coords.clone(),但编译器以多个move行的形式进行了一个奇怪的长而不明确的演讲。

我只是完全偏离Note:,或者可以保存吗?

1 个答案:

答案 0 :(得分:6)

解决方案

你真的很亲密!这有效:

let coord_vec: Vec<_> = x_coords.iter()
    .flat_map(|&x_coord| {
        y_coords.iter().map(move |&y_coord| {
        //                  ^^^^
            [x_coord, y_coord]
        })
    })
    .collect();

我添加的唯一内容是内部闭包前面的move关键字。为什么?让我们试着理解编译器在下面想到的是什么!

但有几点说明:

  • 我将map重命名为flat_map并删除了第二个flat_map来电...您的生活比以前更加复杂; - )
  • 我省略了coord_vec的部分类型注释,因为没有必要

说明

类型x_coordi32(或任何其他整数)。不是参考或任何东西,而是直接的价值。这意味着x_coord由封闭函数拥有,它恰好是一个闭包,特别是“外部”闭包,您传递给flat_map。因此x_coord生活在关闭内部,而不是更长时间。这就是编译器告诉你的。到目前为止一切都很好。

定义第二个闭包(“内部”闭包)时,可以访问环境,特别是x_coord。现在重要的问题是:关闭如何访问其环境?它可以使用不可变引用,可变引用和值来实现。 Rust编译器确定需要对环境的访问类型,并选择有效的“最少侵入性”选项。让我们看看你的代码:编译器发现闭包只需要不可变地借用环境(因为i32Copy,因此闭包可以将其&i32转换为{{1}很容易)。

但在这种情况下,编译器的推理是错误的!借用其环境的封闭导致有限的寿命。在这种情况下,我们需要闭包能够存活更长时间,因此错误。

通过添加i32,我们强制编译器通过值(转移所有权)将环境传递给闭包。这样封闭就没有借用,可以永远活着(满足move)。