为什么闭包可以通过借用 u32 比当前函数长寿?
Why may a closure outlive the current function by borrowing a u32?
我得到
error[E0373]: closure may outlive the current function, but it borrows row_nr
, which is owned by the current function
我不希望这样,因为 row_nr
是一个 u32
,所以我希望它被复制而不是移动:
fn get_neighbours(values: &Vec<Vec<u32>>, row: usize, col: usize) -> Vec<u32> {
vec![
values.get(row - 1).and_then(|cols| cols.get(col)),
values.get(row).and_then(|cols| cols.get(col - 1)),
values.get(row).and_then(|cols| cols.get(col + 1)),
values.get(row + 1).and_then(|cols| cols.get(col)),
].into_iter().filter_map(|value_opt| value_opt.map(|value| *value)).collect()
}
fn get_points(values: Vec<Vec<u32>>) -> Vec<(u32, Vec<u32>)> {
values
.iter()
.enumerate()
.flat_map(|(row_nr, columns)| {
columns.iter().enumerate().map(|(column_nr, height)| {
let neighbours = get_neighbours(&values, row_nr, column_nr);
(*height, neighbours)
})
}).collect()
}
完整错误信息:
--> src/lib.rs:16:44
|
16 | columns.iter().enumerate().map(|(column_nr, height)| {
| ^^^^^^^^^^^^^^^^^^^^^ may outlive borrowed value `row_nr`
17 | let neighbours = get_neighbours(&values, row_nr, column_nr);
| ------ `row_nr` is borrowed here
|
note: closure is returned here
--> src/lib.rs:16:13
|
16 | / columns.iter().enumerate().map(|(column_nr, height)| {
17 | | let neighbours = get_neighbours(&values, row_nr, column_nr);
18 | | (*height, neighbours)
19 | | })
| |______________^
help: to force the closure to take ownership of `row_nr` (and any other referenced variables), use the `move` keyword
|
16 | columns.iter().enumerate().map(move |(column_nr, height)| {
| ++++
现在,错误建议使用 move
,但这会产生问题,因为我只想传递对 values
Vec 的引用(我认为它的寿命不应超过闭包,因为 get_neighbours
从那个 Vec 中获取 u32
s,因此我认为也应该制作副本?)。
我想我在这里误解了一生。对于我误解的任何见解,我将不胜感激。我查看了几个相关问题,但他们似乎要么使用 move
解决它(如上所述,我认为我应该(能够)避免?),或者有多个借用检查器问题,让我很难理解哪些适用于我(例如 )。
I would not expect this, since row_nr
is a u32
, so I'd expect it to be copied rather than moved
这个预期是正确的,假设它首先被移动。在这种情况下,它没有被移动,而是被借用了,因为默认情况下闭包从它们的环境中借用值。要请求 move
,u32
确实会生成副本,您需要明确使用 move
关键字。
正如您所发现的,当您只使用 move
时,您还移动了 values
,它不会编译,无论如何也不是您想要的。仅将一个值移动到闭包中的标准 Rust 习惯用法是使用 move
并显式借用捕获的变量你 不想 想要移动(在你的情况下 values
).例如,这个编译:
.flat_map(|(row_nr, columns)| {
columns.iter().enumerate().map({
let values = &values;
move |(column_nr, height)| {
let neighbours = get_neighbours(values, row_nr, column_nr);
(*height, neighbours)
}
})
})
至于为什么闭包比当前函数长寿的名义问题:请注意,错误消息中的“当前函数”指的是外部闭包,即传递给 flat_map()
的闭包。由于内部闭包成为 map()
返回的迭代器的一部分,并且外部闭包立即 returns 该迭代器,因此内部闭包确实比“当前函数”长寿并且它不能允许借 row_nr
或 columns
。 (但是借用 values
完全没问题,因为 values
比两个闭包都长。)
我得到
error[E0373]: closure may outlive the current function, but it borrows
row_nr
, which is owned by the current function
我不希望这样,因为 row_nr
是一个 u32
,所以我希望它被复制而不是移动:
fn get_neighbours(values: &Vec<Vec<u32>>, row: usize, col: usize) -> Vec<u32> {
vec![
values.get(row - 1).and_then(|cols| cols.get(col)),
values.get(row).and_then(|cols| cols.get(col - 1)),
values.get(row).and_then(|cols| cols.get(col + 1)),
values.get(row + 1).and_then(|cols| cols.get(col)),
].into_iter().filter_map(|value_opt| value_opt.map(|value| *value)).collect()
}
fn get_points(values: Vec<Vec<u32>>) -> Vec<(u32, Vec<u32>)> {
values
.iter()
.enumerate()
.flat_map(|(row_nr, columns)| {
columns.iter().enumerate().map(|(column_nr, height)| {
let neighbours = get_neighbours(&values, row_nr, column_nr);
(*height, neighbours)
})
}).collect()
}
完整错误信息:
--> src/lib.rs:16:44
|
16 | columns.iter().enumerate().map(|(column_nr, height)| {
| ^^^^^^^^^^^^^^^^^^^^^ may outlive borrowed value `row_nr`
17 | let neighbours = get_neighbours(&values, row_nr, column_nr);
| ------ `row_nr` is borrowed here
|
note: closure is returned here
--> src/lib.rs:16:13
|
16 | / columns.iter().enumerate().map(|(column_nr, height)| {
17 | | let neighbours = get_neighbours(&values, row_nr, column_nr);
18 | | (*height, neighbours)
19 | | })
| |______________^
help: to force the closure to take ownership of `row_nr` (and any other referenced variables), use the `move` keyword
|
16 | columns.iter().enumerate().map(move |(column_nr, height)| {
| ++++
现在,错误建议使用 move
,但这会产生问题,因为我只想传递对 values
Vec 的引用(我认为它的寿命不应超过闭包,因为 get_neighbours
从那个 Vec 中获取 u32
s,因此我认为也应该制作副本?)。
我想我在这里误解了一生。对于我误解的任何见解,我将不胜感激。我查看了几个相关问题,但他们似乎要么使用 move
解决它(如上所述,我认为我应该(能够)避免?),或者有多个借用检查器问题,让我很难理解哪些适用于我(例如
I would not expect this, since
row_nr
is au32
, so I'd expect it to be copied rather than moved
这个预期是正确的,假设它首先被移动。在这种情况下,它没有被移动,而是被借用了,因为默认情况下闭包从它们的环境中借用值。要请求 move
,u32
确实会生成副本,您需要明确使用 move
关键字。
正如您所发现的,当您只使用 move
时,您还移动了 values
,它不会编译,无论如何也不是您想要的。仅将一个值移动到闭包中的标准 Rust 习惯用法是使用 move
并显式借用捕获的变量你 不想 想要移动(在你的情况下 values
).例如,这个编译:
.flat_map(|(row_nr, columns)| {
columns.iter().enumerate().map({
let values = &values;
move |(column_nr, height)| {
let neighbours = get_neighbours(values, row_nr, column_nr);
(*height, neighbours)
}
})
})
至于为什么闭包比当前函数长寿的名义问题:请注意,错误消息中的“当前函数”指的是外部闭包,即传递给 flat_map()
的闭包。由于内部闭包成为 map()
返回的迭代器的一部分,并且外部闭包立即 returns 该迭代器,因此内部闭包确实比“当前函数”长寿并且它不能允许借 row_nr
或 columns
。 (但是借用 values
完全没问题,因为 values
比两个闭包都长。)