I want to create a simple linked list and add a value into it. How should the add
method be implemented to make this code output 100 50 10 5
at lin
This is how you need to write it (playground link)
fn add(&mut self, node: Node) {
let item = Some(Box::new(node));
let mut current = self;
loop {
match moving(current).next {
ref mut slot @ None => {
*slot = item;
return;
}
Some(ref mut next) => current = next,
};
}
}
Ok, so what is this?
Step 1, we need to return
immediately after using the value item
. Then the compiler correctly sees that it is only moved from once.
ref mut slot @ None => {
*slot = item;
return;
}
Step 2, to loop with a &mut
pointer that we update along the way is tricky.
By default, Rust will reborrow a &mut
that is dereferenced. It doesn't consume the reference, it just considers it borrowed, as long as the product of the borrow is still alive.
Obviously, this doesn't work very well here. We want a “hand off” from the old current
to the new current
. We can force the &mut
pointer to obey
move semantics instead.
We need this (the identity
function forces move!):
match moving(current).next
we can also write it like this:
let tmp = current;
match tmp.next
or this:
match {current}.next
Step 3, we have no current pointer after we looked up inside it, so adapt the code to that.
ref mut slot
to get a hold on the location of the next value.