I am implementing a singly-linked list. I want to add a method add_all_at_index which will take a new list and an index, insert the new list at the specified index and rearrange the tail of the current list to follow after the new list.
Assume the current list is is [1,2,3,4,5]. Calling add_all_at_index at position 2 with list [8,9,10] should result in [1,2,8,9,10,3,4,5].
I'm especially having trouble in assigning the old tail of the list after the new list. I do not know how to append [3,4,5] to the node with value 10 in the list.
The algorithm I am trying to implement is
Save the current next of the node at (index - 1) in a variable called current_next
Set the next of node at (index - 1) to the head of the list
Iterate to the last of the newly added list and set its next to the current_next.
I am having trouble accomplishing the last step. Below is the code I came up with:
use std::fmt::*;
fn main() {
let list: List<i32> = List::new();
}
#[derive(PartialEq, Debug)]
pub struct Node<T: Debug> {
pub element: T,
pub next: Option<Box<Node<T>>>,
}
#[derive(PartialEq, Debug)]
pub struct List<T: Debug> {
pub head: Option<Node<T>>,
}
impl<T: Debug> List<T> {
pub fn new() -> Self {
List { head: None }
}
pub fn add_all_at_index(&mut self, list_to_add: List<T>, index: usize) {
if index > 0 {
let nth_node = self.get_nth_node_mut(index).take(); // Gets a mutable reference to node at index
nth_node.map(|node| {
let current_next = node.next.take(); // I store a reference to the next of nth node,
node.next = list_to_add.head.map(|node| Box::new(node));
// The 3rd step in the algorithm I mentioned above.
let last_node = self.get_nth_node_mut(self.length()); // This line does not compile. Getting multiple errors in this line
last_node.map(|node| node.next = current_next);
});
} else {
self.head = list_to_add.head
}
}
fn get_nth_node_mut(&mut self, n: usize) -> Option<&mut Node<T>> {
let mut nth_node = self.head.as_mut();
for _ in 0..n {
nth_node = match nth_node {
None => return None,
Some(node) => node.next.as_mut().map(|node| &mut **node),
}
}
nth_node
}
pub fn length(&self) -> usize {
let mut count = 0;
let mut current_node = self.head.as_ref();
while let Some(node) = current_node {
count = count + 1;
current_node = node.next.as_ref().map(|node| &**node)
}
count
}
}
The error I am getting is
warning: unused variable: `list`
--> src/main.rs:4:9
|
4 | let list: List<i32> = List::new();
| ^^^^
|
= note: #[warn(unused_variables)] on by default
= note: to avoid this warning, consider using `_list` instead
error[E0500]: closure requires unique access to `self` but `*self` is already borrowed
--> src/main.rs:26:26
|
25 | let nth_node = self.get_nth_node_mut(index).take(); // Gets a mutable reference to node at index
| ---- borrow occurs here
26 | nth_node.map(|node| {
| ^^^^^^ closure construction occurs here
...
31 | let last_node = self.get_nth_node_mut(self.length()); // This line does not compile. Getting multiple errors in this line
| ---- borrow occurs due to use of `self` in closure
...
34 | } else {
| - borrow ends here
error[E0502]: cannot borrow `**self` as immutable because it is also borrowed as mutable
--> src/main.rs:31:55
|
31 | let last_node = self.get_nth_node_mut(self.length()); // This line does not compile. Getting multiple errors in this line
| ---- ^^^^ immutable borrow occurs here
| |
| mutable borrow occurs here
32 | last_node.map(|node| node.next = current_next);
33 | });
| - mutable borrow ends here
Is this even the right approach to implement add_all_at_index?
I even tried implementing an iterator that returns a mutable reference to a node but I was not able to do that either. I have pasted the entire code in a gist at https://gist.github.com/hardvain/32fca033bb61a5e3bf8bbeeb32fbbd5e
First, the solution:
pub fn add_all_at_index(&mut self, list_to_add: List<T>, index: usize) {
if index > 0 {
let tail = {
let nth_node = self.get_nth_node_mut(index).take();
nth_node.map(|node| {
let current_next = node.next.take();
node.next = list_to_add.head.map(|node| Box::new(node));
current_next
})
};
if let Some(current_next) = tail {
let n = self.length();
let last_node = self.get_nth_node_mut(n);
last_node.map(|node| node.next = current_next);
}
} else {
self.head = list_to_add.head
}
}
Ugly, right? Right. Getting this working required several changes:
I moved step 3 (reattaching the tail of the list) outside of the closure passed to map, so that nth_node (which borrows self) wouldn't still be alive when you try to borrow self again to get the length.
I therefore had to save current_next, so I had the closure return it, and stored the result of map in a new variable called tail. So tail is an Option<Box<Node<T>>>.
I wrapped the tail-reattaching part in an if let to destructure tail and get current_next back out.
Then, I separated self.get_nth_node_mut(self.length()) into two statements to resolve the remaining borrowing error.
Some followup suggestions:
Using .map() for side effects and then ignoring the return value is unidiomatic. Use if let to run code on the content of an Option.
You're ignoring all the None cases. If you try to call add_all_at_index with an index that is out of range, nothing happens to self and list_to_add is just lost. The function should probably return a Result of some kind, or perhaps a bool.
.take() is for getting an Option<T> out of a &mut Option<T>. It doesn't do anything useful to an Option<&mut T>.
|node| Box::new(node) is just Box::new.
Because the first node is boxed but none of the others are, you will have to write a lot of special case code, and there's not a transparent conversion between a Node and a List.
Using get_nth_node_mut in the implementation of add_all_at_index almost forces you to traverse the list twice. Because it's implemented on List instead of on Node, you can't easily get a reference to the last element of the list, so you end up calling length() (making the total number of traversals 3) and then get_nth_node_mut again to dig up the last element.
Some of the ugliness can be mitigated by careful interface design -- for instance, this method becomes cleaner if List has a split_at_index method -- but some of it is just due to the fact that linked lists are ugly. Particularly ugly in Rust, because the language forbids shared mutable references, even temporarily. You would have to use unsafe to write many linked list operations in Rust the same way you would in C.
If you have not already, please read Learning Rust With Entirely Too Many Linked Lists. This book addresses many of the subtleties that arise when you try to implement a linked list in Rust.
Related
Following code gives error if cnode isn't manually dropped after each iteration. As it's going out of scope, it should be automatically dropped, and I think there is no chance of outlive the borrowed value. But it complains with error borrowed value does not live long enough.
#[cfg(feature = "localrun")]
#[derive(Debug, PartialEq, Eq)]
pub struct TreeNode {
pub val: i32,
pub left: Option<Rc<RefCell<TreeNode>>>,
pub right: Option<Rc<RefCell<TreeNode>>>,
}
#[cfg(feature = "localrun")]
impl TreeNode {
#[inline]
pub fn new(val: i32) -> Self {
TreeNode {
val,
left: None,
right: None
}
}
}
// use std::borrow::Borrow;
use std::rc::Rc;
use std::cell::RefCell;
impl Solution {
pub fn max_depth(root: Option<Rc<RefCell<TreeNode>>>) -> i32 {
let mut depth = 0;
let mut vec = vec![];
if let Some(vnode) = &root {
vec.push(vnode.clone());
}
while !vec.is_empty() {
let mut size = vec.len();
while size > 0 {
size -= 1;
let cnode = vec.pop().unwrap();
if let Some(lnode) = cnode.borrow().left.as_ref() {
vec.push(lnode.clone());
}
if let Some(rnode) = cnode.borrow().right.as_ref() {
vec.push(rnode.clone());
}
// drop(cnode); // <---- Uncommenting This fixes the error though
}
}
unimplemented!()
}
}
#[cfg(feature = "localrun")]
struct Solution{}
Edit: Full error msg:
error[E0597]: `cnode` does not live long enough
--> src/w35_w36_easy/n104.rs:105:30
|
105 | if let Some(rnode) = cnode.borrow().right.as_ref() {
| ^^^^^^^^^^^^^^
| |
| borrowed value does not live long enough
| a temporary with access to the borrow is created here ...
...
109 | }
| -
| |
| `cnode` dropped here while still borrowed
| ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Ref<'_, TreeNode>`
|
help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
|
107 | };
| +
I just noticed the helpful error message from compiler. It says to add a semicolon after if block. Actually it fixed the error! Though I'm not sure why semicolon made the difference.
This is actually quite interesting, but requires delving a little more deeply than you might expect.
A while loop is, like most things in Rust, an expression—which is to say that the loop itself evaluates to some value (currently it's always of unit type (), although that could change in the future) and it can therefore be used in expression position, such as on the right hand side of an assignment:
let _: () = while false {};
The block of a while loop is also an expression (albeit one that must also always be of unit type); this value comes from the final expression in the block—which, in your case, is the final if let:
let _: () = if let Some(rnode) = cnode.borrow().right.as_ref() {
vec.push(rnode.clone());
};
The borrow of cnode continues to the end of this expression. Since the expression is evaluated as that of the while loop's block, which is evaluated as that of the while loop expression itself, it actually lives until the while loop expression is evaluated (i.e. the while loop terminates). But your borrow of cnode must not live that long, because subsequent iterations of the loop may need to borrow it again! Hence the error, and the suggestion to add a semicolon at the end of the if let expression (thus converting it into a statement and terminating the borrow of cnode before the end of the while loop block):
if let Some(rnode) = cnode.borrow().right.as_ref() {
vec.push(rnode.clone());
};
Perhaps Rust could/should be more intelligent here, and recognise the borrow cannot possibly be required for so long, but no doubt that would add considerable additional complexity and may make it harder to introduce future changes to the language in a backwards-compatible way.
I have a simple struct like below called TopicTree:
#[derive(Debug, PartialEq, Eq, Hash, Default, Clone)]
// #[allow(dead_code)]
pub struct TopicTree {
topic_name: String,
child: Option<Vec<Box<TopicTree>>>,
data: Option<Vec<String>>
}
And another struct called App which has an impl block as below:
struct App {
// Topic Tree
topic_tree_root:TopicTree,
}
impl App {
pub fn parse_topic_to_tree(& mut self, topic: &str){
let mut temp_node = & mut self.topic_tree_root;
let mut found = false;
for text in topic.split("/") {
for item in temp_node.child.as_mut().unwrap() {
if item.topic_name == text {
temp_node = item.as_mut();
found = true;
break;
}
}
}
}
}
When I try to compile the code, rustc gives me this error:
error[E0499]: cannot borrow `temp_node.child` as mutable more than once at a time
--> src/pub/lib/app.rs:22:26
|
22 | for j in temp_node.child.as_mut().unwrap() {
| ^^^^^^^^^^^^^^^^^^^^^^^^ `temp_node.child` was mutably borrowed here in the previous iteration of the loop
So my question is, isn't variable item local scoped? if it is not as so, how can I iterate over temp_node.child in a nested loop, it is necessary because temp_node is also mutable.
For the inner loop to execute, the compiler has to 1) create an implicit borrow on temp_node in order to 2) borrow temp_node.child, in order to call as_mut() (which takes &mut self) and then bind the result to item. The lifetime of item depends on temp_node being alive, because of this borrow-chain.
In a subsequent iteration of the outer loop, a conflict occurs: If temp_node = item.as_mut() has executed, you need to mutably borrow temp_node in the for item = ... line. But it is already being borrowed to keep temp_item alive, which came from item, which came from temp_node... Here, the circular logic might become apparent: There can be no guarantee - as the code is written, notwithstanding that the data structure wouldn't support this - that temp_node and item end up being the same object, which would cause two mutable borrows on the same value.
There might be some confusion with respect to mut and &mut here. temp_node needs to be mut (as in let mut, because you change temp_node), but it does not need to be a &mut (as in "mutable borrow", because you are not modifying the data behind the reference).
In Rust, I have a BTreeSet that I'm using to keep my values in order. I have a loop that should retrieve and remove the first (lowest) member of the set. I'm using a cloned iterator to retrieve the first member. Here's the code:
use std::collections::BTreeSet;
fn main() {
let mut start_nodes = BTreeSet::new();
// add items to the set
while !start_nodes.is_empty() {
let mut start_iter = start_nodes.iter();
let mut start_iter_cloned = start_iter.cloned();
let n = start_iter_cloned.next().unwrap();
start_nodes.remove(&n);
}
}
This, however, gives me the following compile error:
error[E0502]: cannot borrow `start_nodes` as mutable because it is also borrowed as immutable
--> prog.rs:60:6
|
56 | let mut start_iter = start_nodes.iter();
| ----------- immutable borrow occurs here
...
60 | start_nodes.remove(&n);
| ^^^^^^^^^^^ mutable borrow occurs here
...
77 | }
| - immutable borrow ends here
Why is start_nodes.iter() considered an immutable borrow? What approach should I take instead to get the first member?
I'm using version 1.14.0 (not by choice).
Why is start_nodes.iter() considered an immutable borrow?
Whenever you ask a question like this one, you need to look at the prototype of the function, in this case the prototype of BTreeSet::iter():
fn iter(&self) -> Iter<T>
If we look up the Iter type that is returned, we find that it's defined as
pub struct Iter<'a, T> where T: 'a { /* fields omitted */ }
The lifetime 'a is not explicitly mentioned in the definition of iter(); however, the lifetime elision rules make the function definition equivalent to
fn iter<'a>(&'a self) -> Iter<'a, T>
From this expanded version, you can see that the return value has a lifetime that is bound to the lifetime of the reference to self that you pass in, which is just another way of stating that the function call creates a shared borrow that lives as long as the return value. If you store the return value in a variable, the borrow lives at least as long as the variable.
What approach should I take instead to get the first member?
As noted in the comments, your code works on recent versions of Rust due to non-lexical lifetimes – the compiler figures out by itself that start_iter and start_iter_cloned don't need to live longer than the call to next(). In older versions of Rust, you can artificially limit the lifetime by introducing a new scope:
while !start_nodes.is_empty() {
let n = {
let mut start_iter = start_nodes.iter();
let mut start_iter_cloned = start_iter.cloned();
start_iter_cloned.next().unwrap()
};
start_nodes.remove(&n);
}
However, note that this code is needlessly long-winded. The new iterator you create and its cloning version only live inside the new scope, and they aren't really used for any other purpose, so you could just as well write
while !start_nodes.is_empty() {
let n = start_nodes.iter().next().unwrap().clone();
start_nodes.remove(&n);
}
which does exactly the same, and avoids the issues with long-living borrows by avoiding to store the intermediate values in variables, to ensure their lifetime ends immediately after the expression.
Finally, while you don't give full details of your use case, I strongly suspect that you would be better off with a BinaryHeap instead of a BTreeSet:
use std::collections::BinaryHeap;
fn main() {
let mut start_nodes = BinaryHeap::new();
start_nodes.push(42);
while let Some(n) = start_nodes.pop() {
// Do something with `n`
}
}
This code is shorter, simpler, completely sidesteps the issue with the borrow checker, and will also be more efficient.
Not sure this is the best approach, but I fixed it by introducing a new scope to ensure that the immutable borrow ends before the mutable borrow occurs:
use std::collections::BTreeSet;
fn main() {
let mut start_nodes = BTreeSet::new();
// add items to the set
while !start_nodes.is_empty() {
let mut n = 0;
{
let mut start_iter = start_nodes.iter();
let mut start_iter_cloned = start_iter.cloned();
let x = &mut n;
*x = start_iter_cloned.next().unwrap();
}
start_nodes.remove(&n);
}
}
I have an array of Elements and I want to iterate over it to do some stuff, then iterate over all Elements inside the loop to do something. There is a relation between elements so I want to iterate to all other elements to check something. The elements are mutable references for reasons. It's a bit broad, but I'm trying to be general (maybe I should not).
struct Element;
impl Element {
fn do_something(&self, _e: &Element) {}
}
fn main() {
let mut elements = [Element, Element, Element, Element];
for e in &mut elements {
// Do stuff...
for f in &mut elements {
e.do_something(f);
}
}
}
As expected, I got this error:
error[E0499]: cannot borrow `elements` as mutable more than once at a time
--> src/main.rs:13:18
|
10 | for e in &mut elements {
| -------------
| |
| first mutable borrow occurs here
| first borrow later used here
...
13 | for f in &mut elements {
| ^^^^^^^^^^^^^ second mutable borrow occurs here
I know it's a normal behavior in Rust, but what's the recommended way to avoid this error? Should I copy the elements first? Forget about loops and iterate in a different way? Learn about code design?
Is there a Rusty way to do this?
You can use indexed iteration instead of iterating with iterators. Then, inside the inner loop, you can use split_at_mut to obtain two mutable references into the same slice.
for i in 0..elements.len() {
for j in 0..elements.len() {
let (e, f) = if i < j {
// `i` is in the left half
let (left, right) = elements.split_at_mut(j);
(&mut left[i], &mut right[0])
} else if i == j {
// cannot obtain two mutable references to the
// same element
continue;
} else {
// `i` is in the right half
let (left, right) = elements.split_at_mut(i);
(&mut right[0], &mut left[j])
};
e.do_something(f);
}
}
You cannot do this, period. The rules of references state, emphasis mine:
At any given time, you can have either one mutable reference or any number of immutable references
On the very first iteration, you are trying to get two mutable references to the first element in the array. This must be disallowed.
Your method doesn't require mutable references at all (fn do_something(&self, e: &Element) {}), so the simplest thing is to just switch to immutable iterators:
for e in &elements {
for f in &elements {
e.doSomething(f);
}
}
If you truly do need to perform mutation inside the loop, you will also need to switch to interior mutability. This shifts the enforcement of the rules from compile time to run time, so you will now get a panic when you try to get two mutable references to the same item at the same time:
use std::cell::RefCell;
struct Element;
impl Element {
fn do_something(&mut self, _e: &mut Element) {}
}
fn main() {
let mut elements = [
RefCell::new(Element),
RefCell::new(Element),
RefCell::new(Element),
RefCell::new(Element),
];
for e in &elements {
for f in &elements {
// Note that this will panic as both `e` and `f`
// are the same value to start with
let mut e = e.borrow_mut();
let mut f = f.borrow_mut();
e.do_something(&mut f);
}
}
}
I'm learning Rust and I'm trying to cargo-cult this code into compiling:
use std::vec::Vec;
use std::collections::BTreeMap;
struct Occ {
docnum: u64,
weight: f32,
}
struct PostWriter<'a> {
bytes: Vec<u8>,
occurrences: BTreeMap<&'a [u8], Vec<Occ>>,
}
impl<'a> PostWriter<'a> {
fn new() -> PostWriter<'a> {
PostWriter {
bytes: Vec::new(),
occurrences: BTreeMap::new(),
}
}
fn add_occurrence(&'a mut self, term: &[u8], occ: Occ) {
let occurrences = &mut self.occurrences;
match occurrences.get_mut(term) {
Some(x) => x.push(occ),
None => {
// Add the term bytes to the big vector of all terms
let termstart = self.bytes.len();
self.bytes.extend(term);
// Create a new occurrences vector
let occs = vec![occ];
// Take the appended term as a slice to use as a key
// ERROR: cannot borrow `*occurrences` as mutable more than once at a time
occurrences.insert(&self.bytes[termstart..], occs);
}
}
}
}
fn main() {}
I get an error:
error[E0499]: cannot borrow `*occurrences` as mutable more than once at a time
--> src/main.rs:34:17
|
24 | match occurrences.get_mut(term) {
| ----------- first mutable borrow occurs here
...
34 | occurrences.insert(&self.bytes[termstart..], occs);
| ^^^^^^^^^^^ second mutable borrow occurs here
35 | }
36 | }
| - first borrow ends here
I don't understand... I'm just calling a method on a mutable reference, why would that line involve borrowing?
I'm just calling a method on a mutable reference, why would that line involve borrowing?
When you call a method on an object that's going to mutate the object, you can't have any other references to that object outstanding. If you did, your mutation could invalidate those references and leave your program in an inconsistent state. For example, say that you had gotten a value out of your hashmap and then added a new value. Adding the new value hits a magic limit and forces memory to be reallocated, your value now points off to nowhere! When you use that value... bang goes the program!
In this case, it looks like you want to do the relatively common "append or insert if missing" operation. You will want to use entry for that:
use std::collections::BTreeMap;
fn main() {
let mut map = BTreeMap::new();
{
let nicknames = map.entry("joe").or_insert(Vec::new());
nicknames.push("shmoe");
// Using scoping to indicate that we are done with borrowing `nicknames`
// If we didn't, then we couldn't borrow map as
// immutable because we could still change it via `nicknames`
}
println!("{:?}", map)
}
Because you're calling a method that borrows as mutable
I had a similar question yesterday about Hash, until I noticed something in the docs. The docs for BTreeMap show a method signature for insert starting with fn insert(&mut self..
So when you call .insert, you're implicitly asking that function to borrow the BTreeMap as mutable.