I am fairly new to Rust and want to implement an AVL-Tree.
I am using the following enum to represent my tree:
enum AvlTree<T> {
Leaf,
Node {
left: Box<AvlTree<T>>,
right: Box<AvlTree<T>>,
value: T
}
}
When implementing one of the balance-functions, I'm facing some problems with ownership and borrowing.
I am trying to write a function, which takes an AvlTree<T> and returns another AvlTree<T>. My first attempt was something like this:
fn balance_ll(tree: AvlTree<T>) -> AvlTree<T> {
if let AvlTree::Node {left: t, right: u, value: v} = tree {
if let AvlTree::Node {left: ref tl, right: ref ul, value: ref vl} = *t {
AvlTree::Leaf // Return a new AvlTree here
} else {
tree
}
} else {
tree
}
}
Even with this minimal example, the compiler is returning an error:
error[E0382]: use of partially moved value: `tree`
--> avl.rs:67:17
|
63 | if let AvlTree::Node {left: t, right: u, value: v} = tree {
| - value moved here
...
67 | tree
| ^^^^ value used here after move
|
= note: move occurs because `(tree:AvlTree::Node).left` has type `std::boxed::Box<AvlTree<T>>`, which does not implement the `Copy` trait
I think, I'm understanding the error message correctly, in that destructuring the AvlTree::Node will take away the ownership of the tree example. How can I prevent this from happening? I already tried various things and (de-)referencing the tree-variable only to face more errors.
Additionally, I want to use some of the extracted values like u, tl and vl in the new struct. Is this possible and could you maybe provide a minimal example doing exactly that? I don't need access to the old tree after executing the function.
I think, I'm understanding the error message correctly, in that destructuring the AvlTree::Node will take away the ownership of the tree example.
Yes. If you still need to be able to use tree afterwards, you will either need to make a copy of it:
#[derive(Clone)]
enum AvlTree<T> {...}
fn balance_ll<T: Clone>(tree: AvlTree<T>) -> AvlTree<T> {
let copy = tree.clone();
if let AvlTree::Node { left: t, right: u, value: v } = tree {
if let AvlTree::Node { left: ref tl, right: ref ul, value: ref vl } = *t {
AvlTree::Leaf // Return a new AvlTree here
} else {
copy
}
} else {
tree
}
}
or use a helper function that quickly releases its ownership - but I don't think it is possible without box patterns:
#![feature(box_patterns)]
impl<T> AvlTree<T> {
fn is_left_node(&self) -> bool {
if let &AvlTree::Node { left: ref t, right: ref u, value: ref v } = self {
if let &box AvlTree::Node { left: ref tl, right: ref ul, value: ref vl } = t {
true
} else {
false
}
} else {
false
}
}
}
fn balance_ll<T>(tree: AvlTree<T>) -> AvlTree<T> {
if tree.is_left_node() {
AvlTree::Leaf
} else {
tree
}
}
Since you possibly want to use the destructured values you will probably prefer the clone variant, but maybe the other one will give you some extra ideas.
Related
I am creating simple generic structure representing edge in a graph, and I wanted constructor to switch arguments so the lower would be first.
pub type Index = u16;
pub type Cost = u32;
pub struct Edge<T> {
first: Index,
second: Index,
weight: T,
}
impl<T> Edge<T> {
pub fn new(first: Index, second: Index, weight: T) -> Self {
return if second > first {
Edge { second, first, weight }
} else {
Edge { first, second, weight }
}
}
}
However I am unable to make it work since my tests results in error.
#[test]
fn should_initialize_with_lover_value_first() {
// given
let lower: Index = 234;
let high: Index = 444;
let cost: Cost = 34;
// when
let edge: Edge<Cost> = Edge::new(high, lower, cost);
// then
assert_eq!(edge.first, lower, "edge.first = {}, expected = {}", edge.first, lower);
assert_eq!(edge.second, high, "edge.second = {}, expected = {}", edge.second, high);
}
I got error :
thread 'types::generic::edge::tests::should_initialize_with_lover_value_first' panicked at 'assertion failed: `(left == right)`
left: `444`,
right: `234`: edge.first = 444, expected = 234', src/types/generic/edge.rs:35:9
Am I missing some kind of werid rust behaviour that I am not aware of?
Rust lets you pun on the variable name when it's the same as the field name. So this:
Edge { second, first, weight }
is equivalent to this:
Edge {
second: second,
first: first,
weight: weight,
}
And this:
Edge { first, second, weight }
is equivalent to this:
Edge {
first: first,
second: second,
weight: weight,
}
As you can see, they both are equivalent to each other.
If you want to flip first and second then you can do this instead:
Edge {
first: second,
second: first,
weight,
}
You might want to write it like this, since your code does not change the places where first and second are located:
pub fn new(first: Index, second: Index, weight: T) -> Self {
return if second > first {
Edge { first: second, second: first, weight }
} else {
Edge { first, second, weight }
}
}
I want to implement some basic methods for Trie.
use std::collections::HashMap;
#[derive(Debug)]
struct TrieNode {
chs: HashMap<char, TrieNode>,
value: Option<i32>,
}
#[derive(Debug)]
struct Trie {
root: TrieNode,
}
impl Trie {
fn new() -> Trie {
Trie {
root: TrieNode {
chs: HashMap::new(),
value: None,
},
}
}
fn add_string(&mut self, string: String, value: i32) {
let mut current_node = &mut self.root;
for c in string.chars() {
current_node = current_node.chs.entry(c).or_insert(TrieNode {
chs: HashMap::new(),
value: None,
});
}
current_node.value = Some(value);
}
fn delete(&mut self, key: &String) -> Option<i32> {
if key.is_empty() {
// if key is empty, no need to delete
return None;
}
let mut current_node = &mut self.root;
for (ind, ch) in key.chars().enumerate() {
match current_node.chs.get_mut(&ch) {
Some(node) => {
if ind < key.len() - 1 {
current_node = node;
}
}
None => return None,
}
}
// here current_node is actually the previous node of the deleted node
let temp = current_node.chs.remove(&key.chars().last().unwrap());
match temp {
Some(node) => node.value,
None => None,
}
}
}
The method delete is to remove a key (from a Trie) and returns the value corresponding to that key. However, I got the following error.
error[E0499]: cannot borrow `current_node.chs` as mutable more than once at a time
--> src/main.rs:118:19
|
118 | match current_node.chs.get_mut(&ch) {
| ^^^^^^^^^^^^^^^^ mutable borrow starts here in previous iteration of loop
I'm not exactly sure where the borrow checker is getting tripped up, but you can fix it by hoisting the if check:
let mut current_node = &mut self.root;
for (ind, ch) in key.chars().enumerate() {
if ind < key.len() - 1 {
match current_node.chs.get_mut(&ch) {
Some(node) => {
current_node = node;
}
None => return None,
}
}
}
It skips over even checking if the leaf node exists, but your remove( match already covers that case.
Also, your ind < key.len() - 1 check assumes that the last character is ascii. It may be true for your use case, but if not you can use this answer to iterate until the penultimate character instead.
As the error message explains, you cannot borrow a value (current_node.chs) as mutable more than once at a time.
One solution is to derive the Clone trait for TrieNode. Clone is a common trait for the ability to explicitly duplicate an object:
#[derive(Debug, Clone)]
struct TrieNode {
chs: HashMap<char, TrieNode>,
value: Option<i32>,
}
Now instead of borrowing self.root, you can clone it:
fn delete(&mut self, key: &String) -> Option<i32> {
if key.is_empty() {
return None
}
// clone `self.root`
let mut current_node = self.root.clone();
for (ind, ch) in key.chars().enumerate() {
match current_node.chs.get_mut(&ch) {
Some(node) => {
if ind < key.len() - 1 {
// clone `node`
current_node = node.clone();
}
// ...
If performance is an issue, then cloning is probably not the best idea. However, it is still an option and may or may not suit your use case.
I am new to Rust and want to write linked list in Rust to have fun. I am confused about how to delete a node in the linked list. Here is my simple code.
#[derive(Debug)]
struct Node{
v: usize,
next: Option<Box<Node>>,
}
struct LinkedList {
head: Option<Box<Node>>,
}
impl LinkedList {
fn remove(&mut self, v: usize) -> Option<usize> {
let mut current_node: &mut Option<Box<Node>> = &mut self.head;
loop {
match current_node {
None => break,
Some(node) => {
if node.v == v {
// current_node = what?
// ???????????????
break;
} else {
current_node = &mut node.next;
}
},
};
}
match current_node.take().map(|x| *x) {
Some(node) => {
*current_node = node.next;
return Some(node.v)
},
None => None,
}
}
}
And here is the rust playground. I am using the nightly version and edition = 2018. In the loop, I try to find the node whose next node contains the value that I search for. However, I am confused about what to write in the ?? position.
There isn't really code that can go in that space to fix it; you'll need to make some bigger changes.
One of the problems is that you have mutably borrowed the current node in current_node, but then need to mutate it while that reference still exists.
Making use of non-lexical lifetimes in Edition 2018, you can do:
impl LinkedList {
fn remove(&mut self, v: usize) -> Option<usize> {
let mut current = &mut self.head;
loop {
match current {
None => return None,
Some(node) if node.v == v => {
*current = node.next.take();
return Some(v);
},
Some(node) => {
current = &mut node.next;
}
}
}
}
}
Somehow, using the match guard if node.v == v to make two match arms, instead of using an if condition inside one match arm, lets the borrower checker deduce that this is safe. I'm not sure why the if statement inside the match arm isn't allowed - there are some of the opinion that this could be a bug.
inspire by above answer, my solution is:
fn removeKFromList(mut head: ListNode<i32>, k: i32) -> ListNode<i32> {
if head.is_none() {
return None;
}
let mut current = &mut head;
loop {
match current {
None => break,
Some(node) if node.value == k => {
*current = node.next.take();
},
Some(node) => {
current = &mut node.next;
}
}
}
return head;
}
Here is solution, if you have generic List, which accepts arbitrary type of content type T and returns deleted content to caller:
impl<T> LinkedList<T> {
pub fn remove_f<F: Fn(&T) -> bool>(&mut self, comparator: F) -> Option<T> {
let mut curr_link = &mut self.head;
loop {
match curr_link {
None => return None,
Some(node_ref) if comparator(&node_ref.elem) => {
let node = curr_link.take().unwrap();
*curr_link = node.next;
return Some(node.elem);
},
Some(node) => curr_link = &mut node.next,
};
}
}
}
Use example, assume T = &str and list contains element with value "1" and no element with value "smth":
assert_eq!(list.remove_f(|node| "1".eq(node.deref())), Some("1"));
assert_eq!(list.remove_f(|node| "smth".eq(node.deref())), None);
I'm trying to write a kd-tree implementation, but I keep getting the error cannot move out of borrowed content.
This is my KDTree struct
pub struct KDTree {
pub bounding_box: Aabb,
pub axis: Option<Axis>,
left: Option<Box<KDTree>>,
right: Option<Box<KDTree>>,
pub objects: Option<Vec<Box<Geometry>>>,
}
This method, however, throws that error.
pub fn direct_samples(&self) -> Vec<u32> {
assert!(self.objects.is_some());
let mut direct_samples = Vec::new();
for (i, object) in self.objects
.expect("Expected tree to have objects")
.iter()
.enumerate() {
if object.material().emittance > 0f32 {
direct_samples.push(i as u32);
}
}
if self.left.is_some() {
direct_samples.extend(self.left.unwrap().direct_samples());
}
if self.right.is_some() {
direct_samples.extend(self.right.unwrap().direct_samples());
}
direct_samples
}
I understand that if I change the parameter to self instead of &self, it should work, but then when I call it, it gives the error use of moved value.
pub fn from_objects(objects: Vec<Box<Geometry>>) -> Scene {
let tree = KDTree::from_objects(objects);
Scene {
camera: Camera::new(),
objects: tree,
direct_samples: tree.direct_samples(),
}
}
Do I need to implement Copy on my KDTree? Won't this use a lot of cpu/memory to copy the entire thing?
The reason your code requires ownership of the KDTree is because you are calling Option::expect and Option::unwrap. The docs for these can be found here.
impl<T> Option<T> {
fn unwrap(self) -> T {
...
}
}
So when you are calling unwrap (or expect) the compiler rightly complains that you are taking the elements of your struct by value. To fix this, use the Option::as_ref method.
impl<T> Option<T> {
fn as_ref(&self) -> Option<&T> {
...
}
}
This will turn a reference to an option into an optional reference, which does not require ownership. You can see this in the signature of the function - it takes &self rather than self.
pub fn direct_samples(&self) -> Vec<u32> {
assert!(self.objects.is_some());
let mut direct_samples = Vec::new();
for (i, object) in self.objects.as_ref()
.expect("Expected tree to have objects")
.iter()
.enumerate() {
if object.material().emittance > 0f32 {
direct_samples.push(i as u32);
}
}
if self.left.is_some() {
direct_samples.extend(self.left.as_ref().unwrap().direct_samples());
}
if self.right.is_some() {
direct_samples.extend(self.right.as_ref().unwrap().direct_samples());
}
direct_samples
}
Do I need to implement Copy on my KDTree? Won't this use a lot of cpu/memory to copy the entire thing?
You can't implement Copy on your KDTree because it contains heap-allocated memory (boxes) - Copy means that your type can be copied just by copying its bytes, but that can't happen without invalidating single ownership in this case.
I'm trying to print out a tree (it's a LinkedList right now, but that will be fixed):
use std::io;
use std::rc::Rc;
enum NodeKind {
Branch(Rc<Node>),
Leaf,
}
struct Node {
value: i32,
kind: NodeKind,
}
fn main() {
let leaf = Node { value: 10, kind: NodeKind::Leaf };
let branch = Node { value: 50, kind: NodeKind::Branch(Rc::new(leaf)) };
let root = Node { value: 100, kind: NodeKind::Branch(Rc::new(branch)) };
let mut current = root;
while true {
println!("{}", current.value);
match current.kind {
NodeKind::Branch(next) => {
current = *next;
}
NodeKind::Leaf => {
break;
}
}
}
let mut reader = io::stdin();
let buff = &mut String::new();
let read = reader.read_line(buff);
}
The compiler says:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:24:27
|
24 | current = *next;
| ^^^^^ cannot move out of borrowed content
I'm reading the value only, not changing anything. I'm assigning a value from a reference to another value, trying to dereference an Rc<T> value and store it in a local mut variable.
maybe something like this may work:
while true {
println!("{}", current.value);
match ¤t.kind {
&NodeKind::Branch(next) => {
current = next;
}
&NodeKind::Leaf => {
break;
}
}
}
or maybe
let mut current = &Rc::new(root);
while true {
println!("{}", current.value);
match current.kind {
NodeKind::Branch(next) => {
current = &next;
}
NodeKind::Leaf => {
break;
}
}
}
but I get the same error plus 'next' does not live long enough
There is no need to clone here, it is absolutely possible to do what you want to achieve with references:
use std::rc::Rc;
enum NodeKind {
Branch(Rc<Node>),
Leaf,
}
struct Node {
value: i32,
kind: NodeKind,
}
fn main() {
let leaf = Node { value: 10, kind: NodeKind::Leaf };
let branch = Node { value: 50, kind: NodeKind::Branch(Rc::new(leaf)) };
let root = Node { value: 100, kind: NodeKind::Branch(Rc::new(branch)) };
let mut current = &root;
loop {
println!("{}", current.value);
match current.kind {
NodeKind::Branch(ref next) => {
current = &**next;
}
NodeKind::Leaf => break,
}
}
}
The only important changes from your code is that the pattern in the match is ref next and current is of type &Node.
ref patterns bind their variables by reference, that is, next has type &Rc<Node>. To get &Node from it, you need to dereference it two times to get Node and then reference again to get &Node. Due to Deref coercions, it is also possible to write current = &next, and the compiler will insert an appropriate number of *s for you automatically.
I also changed from while (true) to loop because it is more idiomatic and it helps the compiler to reason about your code.
All traversals of tree-like structures are done like this in Rust. ref patterns allow not to move out of variables, which is absolutely necessary when you only need to read data. You can find more about patterns and how they interact with ownership and borrowing here.
The error is displayed because by default match will perform a move.
After a value is moved (i.e. wasn't taken by reference or method that takes self was called) subsequent calls fail. You'll probably need to clone, which is a property both of your struct and enum lack. Once you add those (#[derive(Clone)) and change current = *next; into current = (*next).clone();, your program will work again!
use std::io;
use std::rc::Rc;
#[derive(Clone)]
enum NodeKind {
Branch(Rc<Node>),
Leaf,
}
#[derive(Clone)]
struct Node {
value: i32,
kind: NodeKind,
}
fn main() {
let leaf = Node { value: 10, kind: NodeKind::Leaf };
let branch = Node { value: 50, kind: NodeKind::Branch(std::rc::Rc::new(leaf)) };
let root = Node { value: 100, kind: NodeKind::Branch(std::rc::Rc::new(branch)) };
let mut current = root;
while true {
println!("{}", current.value);
match current.kind {
NodeKind::Branch(next) => {
current = (*next).clone();
}
NodeKind::Leaf => {
break;
}
}
}
let reader = io::stdin();
let buff = &mut String::new();
let read = reader.read_line(buff);
}
Playground
If you let mut current = &root then you can avoid clone() as per Vladimir's response below (playpen of Vladimir's version).
I can't figure out the issue with 1) yet, but I did find an answer for 2).
At the top, you need to use:
use std::rc::Rc;
instead of
use std::rc;