'How to iterate over a vector without moving it
I have a recursive type which doesn't implement copy
struct Node {
board: Board,
children: Option<Vec<Node>>,
}
I have a Vector of these nodes, I want to call a method on each, and then pass them on to another function.
fn foo() {
let mut nodes: Vec<Node> = get_nodes();
for i in 0..nodes.len() {
nodes[i].grow();
}
pick_node(nodes);
}
This works, but frustratingly
fn foo() {
let nodes: Vec<Node> = get_nodes();
for mut node in nodes {
node.grow();
}
pick_node(nodes);
}
causes an error because "nodes
moved due to this implicit call to .into_iter()
"
Is there a version of for _ in _
that just gets me references to each member of the vector in turn, without moving or copying, like I get when I use a range like in the first version? It's an issue that comes up a lot for me, and it's been hard to find an answer for some reason. Like Clippy says, the iterator is probably faster, and clearer, and just seems idiomatic.
Solution 1:[1]
I believe the methods you're looking for are iter
and/or iter_mut
. So your code will look like the following:
for node in nodes.iter_mut() {
node.grow();
}
Alternatively, &Vec<T>
and &mut Vec<T>
both have IntoIterator
implementations which return the iterator provided by iter
or iter_mut
respectively. So the following is also equivalent to the above:
for node in &mut nodes {
node.grow();
}
Edit
All of the above is correct, just to add a little more clarification:
for pattern in iterable {
/* body */
}
essentially just desugars to the following:
let mut iter = IntoIterator::into_iter(iterable);
loop {
match iter.next() {
Some(pattern) => { /* body */ },
None => break,
}
}
into_iter
requires an owned self
, so that's why your vector is moved when it's substituted in the place of iterable
. Ownership of the vector is transferred to its into_iter
function. On the other hand, when you put &vec
or &mut vec
in the place of iterable
, it's the references which are copied/moved, leaving the original vector in place.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |