无法在闭包内借用 Vec
Unable to borrow a Vec inside of a closure
我有一个 Unit
的矢量。我正在尝试构造一个 Vec<Vec<Unit>>
变量,称为 world
。在创建瓦片的过程中,我需要知道它知道哪些瓦片是相邻的。
我有一个函数 returns 一个由与另一个点相邻的点 ((usize, usize)
) 组成的向量,我正在将其转换为迭代器,在其上进行映射,然后获取与 world
中该位置关联的实际单元(如果存在),或者尚未提交到 world
的当前行。
我需要访问 map
所采用的闭包内的那一行,但我还需要稍后访问它。
fn adjacent((x, y): (usize, usize)) -> Vec<(usize, usize)> {
vec![
(x+1, y),
(x-1, y),
(x, y+1),
(x, y-1),
]
}
struct Unit {
pub tiles: Vec<Tile>,
}
#[derive(Copy, Clone)]
enum Tile {
Floor, Wall, Empty
}
fn main() {
let heightmap = vec![
vec![3, 3, 3, 3, 3, 3],
vec![3, 1, 1, 1, 1, 3],
vec![3, 1, 1, 1, 1, 3],
vec![3, 1, 1, 1, 1, 3],
vec![3, 1, 1, 1, 1, 3],
vec![3, 1, 1, 1, 1, 3],
vec![3, 3, 3, 3, 3, 3],
];
let (sx, sy) = (5, 5);
let mut world: Vec<Vec<Unit>> = vec![];
for y in 0..sy {
let mut line: Vec<Unit> = vec![];
for x in 0..sx {
let mut tiles: Vec<Tile> = vec![];
let height = heightmap[y][x];
let adj = adjacent((x, y))
.iter()
.map(|&(x, y)| {
let list = if y > world.len() {
vec![]
} else if y == world.len() {
line
} else {
world[y]
};
if x >= list.len() {
Tile::Empty
} else {
if height as usize >= list[x].tiles.len() {
Tile::Empty
} else {
list[x].tiles[height as usize]
}
}
})
.collect::<Vec<_>>();
for z in 0..(height as isize - 1) {
tiles.push(Tile::Wall);
}
line.push(Unit {
tiles: tiles,
});
}
world.push(line);
}
}
这里是 Rust Playground.
我宁愿将 unwrap_or
与 get
等结合使用,但这会导致其他临时值错误,而且无论如何都会更复杂,所以上面的代码,而可能不是最优的,在我仍然复制错误的同时尽可能简单。我发现我在使用 Rust 时遇到的很多错误是因为我正在做的并不是解决它的最佳方法,所以如果有更惯用的方法,我当然想知道。
我试图使 Unit
可克隆(派生 Clone
和 Copy
)但 Rust 出于某种原因不允许我这样做,即使它全部由是可克隆的载体,如果它们的成员是。
这是您的问题的一个小例子:
fn main() {
let mut line = vec![1];
let something_to_iterate_over = vec![true, false, true];
for _ in 0..2 {
let _dummy: Vec<_> = something_to_iterate_over
.iter()
.map(|&value| {
let maybe_moved_line = if value { vec![] } else { line };
() // Don't care about the return value
})
.collect();
line.push(2);
}
}
错误消息的第一部分是:
error[E0382]: capture of moved value: `line`
--> src/main.rs:9:67
|
8 | .map(|&value| {
| -------- value moved (into closure) here
9 | let maybe_moved_line = if value { vec![] } else { line };
| ^^^^ value captured here after move
|
= note: move occurs because `line` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `line`
--> src/main.rs:14:9
|
8 | .map(|&value| {
| -------- value moved (into closure) here
...
14 | line.push(2);
| ^^^^ value used here after move
|
= note: move occurs because `line` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
由于错误消息试图传达,代码在 map
调用后不再拥有变量 line
的所有权,因为所有权已转移到闭包。
该代码试图将单个 Vec
提供给其他人,同时自己保留它,而这根本不是所有权的运作方式。我不能把我的车给你,然后每天开着它——它不是我开的!
让您的代码编译的最小更改是停止尝试放弃唯一的 line
,而是根据需要克隆它:
- 将
#[derive(Clone)]
添加到Unit
- 在闭包内克隆
line
和 world[y]
:line.clone()
、world[y].clone()
执行此操作后,代码永远不会放弃 line
的所有权,因此可以在需要时对其进行克隆。
我有一个 Unit
的矢量。我正在尝试构造一个 Vec<Vec<Unit>>
变量,称为 world
。在创建瓦片的过程中,我需要知道它知道哪些瓦片是相邻的。
我有一个函数 returns 一个由与另一个点相邻的点 ((usize, usize)
) 组成的向量,我正在将其转换为迭代器,在其上进行映射,然后获取与 world
中该位置关联的实际单元(如果存在),或者尚未提交到 world
的当前行。
我需要访问 map
所采用的闭包内的那一行,但我还需要稍后访问它。
fn adjacent((x, y): (usize, usize)) -> Vec<(usize, usize)> {
vec![
(x+1, y),
(x-1, y),
(x, y+1),
(x, y-1),
]
}
struct Unit {
pub tiles: Vec<Tile>,
}
#[derive(Copy, Clone)]
enum Tile {
Floor, Wall, Empty
}
fn main() {
let heightmap = vec![
vec![3, 3, 3, 3, 3, 3],
vec![3, 1, 1, 1, 1, 3],
vec![3, 1, 1, 1, 1, 3],
vec![3, 1, 1, 1, 1, 3],
vec![3, 1, 1, 1, 1, 3],
vec![3, 1, 1, 1, 1, 3],
vec![3, 3, 3, 3, 3, 3],
];
let (sx, sy) = (5, 5);
let mut world: Vec<Vec<Unit>> = vec![];
for y in 0..sy {
let mut line: Vec<Unit> = vec![];
for x in 0..sx {
let mut tiles: Vec<Tile> = vec![];
let height = heightmap[y][x];
let adj = adjacent((x, y))
.iter()
.map(|&(x, y)| {
let list = if y > world.len() {
vec![]
} else if y == world.len() {
line
} else {
world[y]
};
if x >= list.len() {
Tile::Empty
} else {
if height as usize >= list[x].tiles.len() {
Tile::Empty
} else {
list[x].tiles[height as usize]
}
}
})
.collect::<Vec<_>>();
for z in 0..(height as isize - 1) {
tiles.push(Tile::Wall);
}
line.push(Unit {
tiles: tiles,
});
}
world.push(line);
}
}
这里是 Rust Playground.
我宁愿将 unwrap_or
与 get
等结合使用,但这会导致其他临时值错误,而且无论如何都会更复杂,所以上面的代码,而可能不是最优的,在我仍然复制错误的同时尽可能简单。我发现我在使用 Rust 时遇到的很多错误是因为我正在做的并不是解决它的最佳方法,所以如果有更惯用的方法,我当然想知道。
我试图使 Unit
可克隆(派生 Clone
和 Copy
)但 Rust 出于某种原因不允许我这样做,即使它全部由是可克隆的载体,如果它们的成员是。
这是您的问题的一个小例子:
fn main() {
let mut line = vec![1];
let something_to_iterate_over = vec![true, false, true];
for _ in 0..2 {
let _dummy: Vec<_> = something_to_iterate_over
.iter()
.map(|&value| {
let maybe_moved_line = if value { vec![] } else { line };
() // Don't care about the return value
})
.collect();
line.push(2);
}
}
错误消息的第一部分是:
error[E0382]: capture of moved value: `line`
--> src/main.rs:9:67
|
8 | .map(|&value| {
| -------- value moved (into closure) here
9 | let maybe_moved_line = if value { vec![] } else { line };
| ^^^^ value captured here after move
|
= note: move occurs because `line` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `line`
--> src/main.rs:14:9
|
8 | .map(|&value| {
| -------- value moved (into closure) here
...
14 | line.push(2);
| ^^^^ value used here after move
|
= note: move occurs because `line` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
由于错误消息试图传达,代码在 map
调用后不再拥有变量 line
的所有权,因为所有权已转移到闭包。
该代码试图将单个 Vec
提供给其他人,同时自己保留它,而这根本不是所有权的运作方式。我不能把我的车给你,然后每天开着它——它不是我开的!
让您的代码编译的最小更改是停止尝试放弃唯一的 line
,而是根据需要克隆它:
- 将
#[derive(Clone)]
添加到Unit
- 在闭包内克隆
line
和world[y]
:line.clone()
、world[y].clone()
执行此操作后,代码永远不会放弃 line
的所有权,因此可以在需要时对其进行克隆。