我正在编写一个函数,该函数应该采用几个向量并将它们的笛卡尔积(它们的所有对组合)生成为行主要顺序的向量。换句话说,如果我有
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:
,或者可以保存吗?
答案 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_coord
是i32
(或任何其他整数)。不是参考或任何东西,而是直接的价值。这意味着x_coord
由封闭函数拥有,它恰好是一个闭包,特别是“外部”闭包,您传递给flat_map
。因此x_coord
生活在关闭内部,而不是更长时间。这就是编译器告诉你的。到目前为止一切都很好。
定义第二个闭包(“内部”闭包)时,可以访问环境,特别是x_coord
。现在重要的问题是:关闭如何访问其环境?它可以使用不可变引用,可变引用和值来实现。 Rust编译器确定需要对环境的访问类型,并选择有效的“最少侵入性”选项。让我们看看你的代码:编译器发现闭包只需要不可变地借用环境(因为i32
是Copy
,因此闭包可以将其&i32
转换为{{1}很容易)。
但在这种情况下,编译器的推理是错误的!借用其环境的封闭导致有限的寿命。在这种情况下,我们需要闭包能够存活更长时间,因此错误。
通过添加i32
,我们强制编译器通过值(转移所有权)将环境传递给闭包。这样封闭就没有借用,可以永远活着(满足move
)。