Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to assign new value to an Option<Box<_>> variable?

Tags:

rust

I am writing a tree in Rust and I want to implement a function:left which can turn a tree's root into the tree's root's left child. Here is my code:

struct Node {
    value: i32,
    left: Option<Box<Node>>,
    right: Option<Box<Node>>,
}

struct Tree {
    root: Option<Box<Node>>,
}

enum Error {
    DuplicateValue,
    NotFound,
    EmptyTree
}

impl Tree {
    fn left(&mut self) -> Result<(), Error> {
        match self.root {
            Option::None => return Err(Error::EmptyTree),
            Option::Some(ref mut node) => {
                *node = node.left.as_ref().unwrap();
                return Ok(())
            }
        }
    }
}

and the error says

mismatched types
expected struct `Box<Node>`
found reference `&Box<Node>`

I have tried many methods and look up a lot of information but I still cannot fix this. I think it is a very simple thing in C, just like:

*root = *(root->left);

but why is it so hard in Rust? Can anyone help me?

like image 815
dubugger Avatar asked Oct 25 '25 10:10

dubugger


1 Answers

Since your code looks like it throws away the whole right branch and the root node when calling left, i.e. you aren't concerned with the original root (it will be dropped after the assignment), you can simply take the left node out of the Option:

impl Tree {
    fn left(&mut self) -> Result<(), Error> {
        match self.root {
            Option::None => Err(Error::EmptyTree),
            Option::Some(ref mut node) => {
                *node = node.left.take().unwrap();
                Ok(())
            }
        }
    }
}

Playground

Note however that this will panic if the left subtree is empty. If you want to make self empty in this case, you want to replace the whole Option, not the value inside it. In this case, you have to first do the matching, return early in the empty case, and only then, after the root is no longer borrowed, do the replacement:

impl Tree {
    fn left(&mut self) -> Result<(), Error> {
        let node = match self.root {
            Option::None => return Err(Error::EmptyTree),
            Option::Some(ref mut node) => node.left.take(),
        };
        self.root = node;
        Ok(())
    }
}
like image 71
Cerberus Avatar answered Oct 27 '25 02:10

Cerberus



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!