Peek inmplementation for linked list in rust - rust

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=693594655ea355b40e2175542c653879
I want peek() to remove the last element of the list, returning data. What am I missing?
type Link<T> = Option<Box<Node<T>>>;
struct Node<T> {
pub data: T,
pub next: Link<T>,
}
struct List<T> {
pub head: Link<T>,
}
impl<T> List<T> {
fn peek(&mut self) -> Option<T> {
let mut node = &self.head;
while let Some(cur_node) = &mut node {
if cur_node.next.is_some() {
node = &cur_node.next;
continue;
}
}
let last = node.unwrap();
let last = last.data;
return Some(last);
}
}
#[test]
fn peek_test() {
let mut q = List::new();
q.push(1);
q.push(2);
q.push(3);
assert_eq!(q.empty(), false);
assert_eq!(q.peek().unwrap(), 1);
assert_eq!(q.peek().unwrap(), 2);
assert_eq!(q.peek().unwrap(), 3);
assert_eq!(q.empty(), true);
}
To save the head, I need to access the elements by reference, but the puzzle does not fit in my head. I looked at "too-many-lists", but the value is simply returned by reference, and I would like to remove the tail element.

To make this work you have to switch from taking a shared reference (&) to a mutable one.
This results in borrow checker errors with your code wihch is why I had to change the while let loop into one
which checks if the next element is Some and only then borrows node's content mutably and advances it.
At last I Option::take that last element and return it's data. I use Option::map to avoid having to unwrap which would panic for empty lists anyways if you wanted to keep your variant you should replace unwrap with the try operator ?.
So in short you can implement a pop_back like this:
pub fn pop_back(&mut self) -> Option<T> {
let mut node = &mut self.head;
while node.as_ref().map(|n| n.next.is_some()).unwrap_or_default() {
node = &mut node.as_mut().unwrap().next;
}
node.take().map(|last| last.data)
}

I suggest something like below, Just because I spent time on it .-)
fn peek(&mut self) -> Option<T> {
match &self.head {
None => return None,
Some(v) =>
if v.next.is_none() {
let last = self.head.take();
let last = last.unwrap().data;
return Some(last);
}
}
let mut current = &mut self.head;
loop {
match current {
None => return None,
Some(node) if node.next.is_some() && match &node.next { None => false, Some(v) => v.next.is_none()} => {
let last = node.next.take();
let last = last.unwrap().data;
return Some(last);
},
Some(node) => {
current = &mut node.next;
}
}
}
}

Related

How to manage properly ownership with borrowing in Rust?

I'm quite newbie in the Rust world and still not fully understand how ownership/borrowing/lifetime works. I have this example to demonstrate a struggle:
struct Node {
value: bool,
next: Option<Box<Node>>
}
fn populate(next: &mut Option<Box<Node>>) -> Option<Node> {
let node = Node { value: true, next: None };
let result = Some(Box::new(node));
*next = result;
Some(*next.unwrap())
}
fn main() {
let mut node = Node {
value: false,
next: None
};
let result = populate(&mut node.next);
println!("{}", node.unwrap().value);
println!("{}", result.unwrap().value);
}
I don't understand why move this way works:
fn populate(next: &mut Option<Box<Node>>) -> Option<Node> {
let node = Node { value: true, next: None };
let result = Some(Box::new(node));
// *next = result;
Some(*result.unwrap() /* *next.unwrap() */)
}
But another way doesn't:
fn populate(next: &mut Option<Box<Node>>) -> Option<Node> {
let node = Node { value: true, next: None };
let result = Some(Box::new(node));
*next = result;
Some(*(*next.as_ref().unwrap())) // or Some(*next.unwrap())
}
How to proper transfer ownership (like in example above) without copying but with borrowing mutating next reference (and not adding extra parameters)? I'm still not clear with this part...
If you want populate to return a reference to the new Node placed inside next, the reference needs to be part of the return type. You can't move (transfer ownership of) the node into next while also returning it; that's not how ownership works:
fn populate(next: &mut Option<Box<Node>>) -> Option<&mut Node> {
// here: ^^^^
You might try to return Some(&mut *next.unwrap()), but that won't work because unwrap takes self by value. Fortunately, there's a convenient function on Option that will take you straight from &mut Option<Box<Node>> to Option<&mut Node>, as_deref_mut:
fn populate(next: &mut Option<Box<Node>>) -> Option<&mut Node> {
let node = Node {
value: true,
next: None,
};
*next = Some(Box::new(node));
next.as_deref_mut()
}
Also read
Cannot move out of borrowed content / cannot move out of behind a shared reference
Learn Rust With Entirely Too Many Linked Lists
fn populate(next: &mut Option<Box<Node>>) -> Option<Node> {
let node = Node { value: true, next: None };
let result = Some(Box::new(node));
*next = result;
Some(*result.unwrap() /* *next.unwrap() */)
}
Massaging the code as the compiler suggests may lead to something you wrote. Now, taking it, introducing intermediate variables and annotating types (to see what's going on) gives this:
fn populate2(next: &mut Option<Box<Node>>) -> Option<Node> {
let node : Node = Node { value: true, next: None };
let result : Option<Box<Node>> = Some(Box::new(node));
*next = result;
let next_as_ref : Option<&Box<Node>> = next.as_ref();
let next_as_ref_unwrap : &Box<Node> = next_as_ref.unwrap();
let next_as_ref_unwrap_deref : Box<Node> = *next_as_ref_unwrap; // <- error here!
Some(*next_as_ref_unwrap_deref) // or Some(*next.unwrap())
}
let next_as_ref_unwrap_deref : Box<Node> = *next_as_ref_unwrap; fails, because next_as_ref_unwrap is a borrowed Box<Node>, i.e. a &Box<Node>. Dereferencing (i.e. *) next_as_ref_unwrap tries to move, which cannot be done from a borrowed variable.
The problem is that you have next, which contains (essentially) a Node, however, you want to return a Node. This poses the question: Do you want to return another (i.e. new Node), or do you want to extract (i.e. take) the Node from next and return it. In case you want to take and return it:
fn populate(next: &mut Option<Box<Node>>) -> Option<Node> {
let node = Node { value: true, next: None };
let result = Some(Box::new(node));
*next = result;
next.take().map(|boxed_node| *boxed_node)
}
The above code compiles, but is - at least - dubious, as it accepts a next that is essentially used as a local variable and made None afterwards (because we take from it).
You probably want to decide what populate actually should do.
Should it modify None? Why the return value Option<None>? Should it return next's old value? (Why return Option<Node> instead of Option<Box<Node>> then?)
Code:
fn populate_returning_old_val(next: &mut Option<Box<Node>>) -> Option<Node> {
std::mem::replace(
next,
Some(Box::new(Node { value: true, next: None }))
).take().map(|boxed_node| *boxed_node)
}

Rust: Implement AVL Tree and error: thread 'main' panicked at 'already borrowed: BorrowMutError'

I have the following tree structure:
use std::cell::RefCell;
use std::rc::Rc;
use std::cmp;
use std::cmp::Ordering;
type AVLTree<T> = Option<Rc<RefCell<TreeNode<T>>>>;
#[derive(Debug, PartialEq, Clone)]
struct TreeSet<T: Ord> {
root: AVLTree<T>,
}
impl<T: Ord> TreeSet<T> {
fn new() -> Self {
Self {
root: None
}
}
fn insert(&mut self, value: T) -> bool {
let current_tree = &mut self.root;
while let Some(current_node) = current_tree {
let node_key = &current_node.borrow().key;
match node_key.cmp(&value) {
Ordering::Less => { let current_tree = &mut current_node.borrow_mut().right; },
Ordering::Equal => {
return false;
}
Ordering::Greater => { let current_tree = &mut current_node.borrow_mut().left; },
}
}
*current_tree = Some(Rc::new(RefCell::new(TreeNode {
key: value,
left: None,
right: None,
parent: None
})));
true
}
}
#[derive(Clone, Debug, PartialEq)]
struct TreeNode<T: Ord> {
pub key: T,
pub parent: AVLTree<T>,
left: AVLTree<T>,
right: AVLTree<T>,
}
fn main() {
let mut new_avl_tree: TreeSet<u32> = TreeSet::new();
new_avl_tree.insert(3);
new_avl_tree.insert(5);
println!("Tree: {:#?}", &new_avl_tree);
}
Building with cargo build is fine, but when I run cargo run, I got the below error:
thread 'main' panicked at 'already borrowed: BorrowMutError', src\libcore\result.rs:1165:5
note: run with RUST_BACKTRACE=1 environment variable to display a backtrace. error: process didn't
exit successfully: target\debug\avl-tree.exe (exit code: 101)
If i just call insert(3), it will be fine and my tree gets printed correctly. However, if I insert(5) after insert(3), I will get that error.
How do I fix that?
Manually implementing data structures such as linked list, tree, graph are not task for novices, because of memory safety rules in language. I suggest you to read Too Many Linked Lists tutorial, which discusses how to implement safe and unsafe linked lists in Rust right way.
Also read about name shadowing.
Your error is that inside a cycle you try to borrow mutable something which is already borrowed as immutable.
let node_key = &current_node.borrow().key; // Borrow as immutable
match node_key.cmp(&value) {
Ordering::Less => { let current_tree = &mut current_node.borrow_mut().right; }, // Create a binding which will be immediately deleted and borrow as mutable.
And I recommend you to read Rust book to learn rust.
First let us correct your algorithm. The following lines are incorrect:
let current_tree = &mut current_node.borrow_mut().right;
...
let current_tree = &mut current_node.borrow_mut().left;
Both do not reassign a value to current_tree but create a new (unused) one (#Inline refers to it as Name shadowing). Remove the let and make current_tree mut.
Now we get a compiler error temporary value dropped while borrowed. Probably the compiler error message did mislead you. It tells you to use let to increase the lifetime, and this would be right if you used the result in the same scope, but no let can increase the lifetime beyond the scope.
The problem is that you cannot pass out a reference to a value owned by a loop (as current_node.borrow_mut.right). So it would be better to use current_tree as owned variable. Sadly this means that many clever tricks in your code will not work any more.
Another problem in the code is the multiple borrow problem (your original runtime warning is about this). You cannot call borrow() and borrow_mut() on the same RefCell without panic(that is the purpose of RefCell).
So after finding the problems in your code, I got interested in how I would write the code. And now that it is written, I thought it would be fair to share it:
fn insert(&mut self, value: T) -> bool {
if let None = self.root {
self.root = TreeSet::root(value);
return true;
}
let mut current_tree = self.root.clone();
while let Some(current_node) = current_tree {
let mut borrowed_node = current_node.borrow_mut();
match borrowed_node.key.cmp(&value) {
Ordering::Less => {
if let Some(next_node) = &borrowed_node.right {
current_tree = Some(next_node.clone());
} else {
borrowed_node.right = current_node.child(value);
return true;
}
}
Ordering::Equal => {
return false;
}
Ordering::Greater => {
if let Some(next_node) = &borrowed_node.left {
current_tree = Some(next_node.clone());
} else {
borrowed_node.left = current_node.child(value);
return true;
}
}
};
}
true
}
//...
trait NewChild<T: Ord> {
fn child(&self, value: T) -> AVLTree<T>;
}
impl<T: Ord> NewChild<T> for Rc<RefCell<TreeNode<T>>> {
fn child(&self, value: T) -> AVLTree<T> {
Some(Rc::new(RefCell::new(TreeNode {
key: value,
left: None,
right: None,
parent: Some(self.clone()),
})))
}
}
One will have to write the two methods child(value:T) and root(value:T) to make this compile.

How can I return the combination of two borrowed RefCells?

I have a struct with two Vecs wrapped in RefCells. I want to have a method on that struct that combines the two vectors and returns them as a new RefCell or RefMut:
use std::cell::{RefCell, RefMut};
struct World {
positions: RefCell<Vec<Option<Position>>>,
velocities: RefCell<Vec<Option<Velocity>>>,
}
type Position = i32;
type Velocity = i32;
impl World {
pub fn new() -> World {
World {
positions: RefCell::new(vec![Some(1), None, Some(2)]),
velocities: RefCell::new(vec![None, None, Some(1)]),
}
}
pub fn get_pos_vel(&self) -> RefMut<Vec<(Position, Velocity)>> {
let mut poses = self.positions.borrow_mut();
let mut vels = self.velocities.borrow_mut();
poses
.iter_mut()
.zip(vels.iter_mut())
.filter(|(e1, e2)| e1.is_some() && e2.is_some())
.map(|(e1, e2)| (e1.unwrap(), e2.unwrap()))
.for_each(|elem| println!("{:?}", elem));
}
}
fn main() {
let world = World::new();
world.get_pos_vel();
}
How would I return the zipped contents of the vectors as a new RefCell? Is that possible?
I know there is RefMut::map() and I tried to nest two calls to map, but didn't succeed with that.
You want to be able to modify the positions and velocities. If these have to be stored in two separate RefCells, what about side-stepping the problem and using a callback to do the modification?
use std::cell::RefCell;
struct World {
positions: RefCell<Vec<Option<Position>>>,
velocities: RefCell<Vec<Option<Velocity>>>,
}
type Position = i32;
type Velocity = i32;
impl World {
pub fn new() -> World {
World {
positions: RefCell::new(vec![Some(1), None, Some(2)]),
velocities: RefCell::new(vec![None, None, Some(1)]),
}
}
pub fn modify_pos_vel<F: FnMut(&mut Position, &mut Velocity)>(&self, mut f: F) {
let mut poses = self.positions.borrow_mut();
let mut vels = self.velocities.borrow_mut();
poses
.iter_mut()
.zip(vels.iter_mut())
.filter_map(|pair| match pair {
(Some(e1), Some(e2)) => Some((e1, e2)),
_ => None,
})
.for_each(|pair| f(pair.0, pair.1))
}
}
fn main() {
let world = World::new();
world.modify_pos_vel(|position, velocity| {
// Some modification goes here, for example:
*position += *velocity;
});
}
If you want to return a new Vec, then you don't need to wrap it in RefMut or RefCell:
Based on your code with filter and map
pub fn get_pos_vel(&self) -> Vec<(Position, Velocity)> {
let mut poses = self.positions.borrow_mut();
let mut vels = self.velocities.borrow_mut();
poses.iter_mut()
.zip(vels.iter_mut())
.filter(|(e1, e2)| e1.is_some() && e2.is_some())
.map(|(e1, e2)| (e1.unwrap(), e2.unwrap()))
.collect()
}
Alternative with filter_map
poses.iter_mut()
.zip(vels.iter_mut())
.filter_map(|pair| match pair {
(Some(e1), Some(e2)) => Some((*e1, *e2)),
_ => None,
})
.collect()
You can wrap it in RefCell with RefCell::new, if you really want to, but I would leave it up to the user of the function to wrap it in whatever they need.

How to implement an addition method of linked list?

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 line 42, the second root.print() call?
use std::rc::Rc;
struct Node {
value: i32,
next: Option<Box<Node>>,
}
impl Node {
fn print(&self) {
let mut current = self;
loop {
println!("{}", current.value);
match current.next {
Some(ref next) => {
current = &**next;
}
None => break,
}
}
}
fn add(&mut self, node: Node) {
let item = Some(Box::new(node));
let mut current = self;
loop {
match current.next {
None => current.next = item,
_ => {}
//Some(next) => { current = next; }
}
}
}
}
fn main() {
let leaf = Node {
value: 10,
next: None,
};
let branch = Node {
value: 50,
next: Some(Box::new(leaf)),
};
let mut root = Node {
value: 100,
next: Some(Box::new(branch)),
};
root.print();
let new_leaf = Node {
value: 5,
next: None,
};
root.add(new_leaf);
root.print();
}
(Playground)
I rewrote the function like this:
fn add(&mut self, node: Node) {
let item = Some(Box::new(node));
let mut current = self;
loop {
match current {
&mut Node {
value: _,
next: None,
} => current.next = item,
_ => {}
//Some(next) => { current = next; }
}
}
}
but the compiler says
error[E0382]: use of moved value: `item`
--> <anon>:28:40
|
28 | None => current.next = item,
| ^^^^ value moved here in previous iteration of loop
|
= note: move occurs because `item` has type `std::option::Option<std::boxed::Box<Node>>`, which does not implement the `Copy` trait
I don't understand why it says that item was previously moved if it's used only once, and how the Some(_) branch should be implemented to iterate through the list?
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.
Use ref mut slot to get a hold on the location of the next value.

Using the same iterator multiple times in Rust

Editor's note: This code example is from a version of Rust prior to 1.0 when many iterators implemented Copy. Updated versions of this code produce a different errors, but the answers still contain valuable information.
I'm trying to write a function to split a string into clumps of letters and numbers; for example, "test123test" would turn into [ "test", "123", "test" ]. Here's my attempt so far:
pub fn split(input: &str) -> Vec<String> {
let mut bits: Vec<String> = vec![];
let mut iter = input.chars().peekable();
loop {
match iter.peek() {
None => return bits,
Some(c) => if c.is_digit() {
bits.push(iter.take_while(|c| c.is_digit()).collect());
} else {
bits.push(iter.take_while(|c| !c.is_digit()).collect());
}
}
}
return bits;
}
However, this doesn't work, looping forever. It seems that it is using a clone of iter each time I call take_while, starting from the same position over and over again. I would like it to use the same iter each time, advancing the same iterator over all the each_times. Is this possible?
As you identified, each take_while call is duplicating iter, since take_while takes self and the Peekable chars iterator is Copy. (Only true before Rust 1.0 — editor)
You want to be modifying the iterator each time, that is, for take_while to be operating on an &mut to your iterator. Which is exactly what the .by_ref adaptor is for:
pub fn split(input: &str) -> Vec<String> {
let mut bits: Vec<String> = vec![];
let mut iter = input.chars().peekable();
loop {
match iter.peek().map(|c| *c) {
None => return bits,
Some(c) => if c.is_digit(10) {
bits.push(iter.by_ref().take_while(|c| c.is_digit(10)).collect());
} else {
bits.push(iter.by_ref().take_while(|c| !c.is_digit(10)).collect());
},
}
}
}
fn main() {
println!("{:?}", split("123abc456def"))
}
Prints
["123", "bc", "56", "ef"]
However, I imagine this is not correct.
I would actually recommend writing this as a normal for loop, using the char_indices iterator:
pub fn split(input: &str) -> Vec<String> {
let mut bits: Vec<String> = vec![];
if input.is_empty() {
return bits;
}
let mut is_digit = input.chars().next().unwrap().is_digit(10);
let mut start = 0;
for (i, c) in input.char_indices() {
let this_is_digit = c.is_digit(10);
if is_digit != this_is_digit {
bits.push(input[start..i].to_string());
is_digit = this_is_digit;
start = i;
}
}
bits.push(input[start..].to_string());
bits
}
This form also allows for doing this with much fewer allocations (that is, the Strings are not required), because each returned value is just a slice into the input, and we can use lifetimes to state this:
pub fn split<'a>(input: &'a str) -> Vec<&'a str> {
let mut bits = vec![];
if input.is_empty() {
return bits;
}
let mut is_digit = input.chars().next().unwrap().is_digit(10);
let mut start = 0;
for (i, c) in input.char_indices() {
let this_is_digit = c.is_digit(10);
if is_digit != this_is_digit {
bits.push(&input[start..i]);
is_digit = this_is_digit;
start = i;
}
}
bits.push(&input[start..]);
bits
}
All that changed was the type signature, removing the Vec<String> type hint and the .to_string calls.
One could even write an iterator like this, to avoid having to allocate the Vec. Something like fn split<'a>(input: &'a str) -> Splits<'a> { /* construct a Splits */ } where Splits is a struct that implements Iterator<&'a str>.
take_while takes self by value: it consumes the iterator. Before Rust 1.0 it also was unfortunately able to be implicitly copied, leading to the surprising behaviour that you are observing.
You cannot use take_while for what you are wanting for these reasons. You will need to manually unroll your take_while invocations.
Here is one of many possible ways of dealing with this:
pub fn split(input: &str) -> Vec<String> {
let mut bits: Vec<String> = vec![];
let mut iter = input.chars().peekable();
loop {
let seeking_digits = match iter.peek() {
None => return bits,
Some(c) => c.is_digit(10),
};
if seeking_digits {
bits.push(take_while(&mut iter, |c| c.is_digit(10)));
} else {
bits.push(take_while(&mut iter, |c| !c.is_digit(10)));
}
}
}
fn take_while<I, F>(iter: &mut std::iter::Peekable<I>, predicate: F) -> String
where
I: Iterator<Item = char>,
F: Fn(&char) -> bool,
{
let mut out = String::new();
loop {
match iter.peek() {
Some(c) if predicate(c) => out.push(*c),
_ => return out,
}
let _ = iter.next();
}
}
fn main() {
println!("{:?}", split("test123test"));
}
This yields a solution with two levels of looping; another valid approach would be to model it as a state machine one level deep only. Ask if you aren’t sure what I mean and I’ll demonstrate.

Resources