简体   繁体   中英

refcell rc<refcell<>> doesn't change

Here is my simplified code. I need to change the pdp_state in a function. but the state remain 'a'. I don't figure out why cloning Rc does not work. I also checked this cloning out side a structure an it worked.

#[derive(Clone,Copy)]
enum PDPStatus{
    a,
    b
}
struct network{
    pdp_state:Rc<RefCell<PDPStatus>>,
}
impl network{
    fn set(&mut self){
        let mut t = *self.pdp_state.clone().borrow_mut();
        match t {
            a => {let m1 = self.pdp_state.clone();
                let mut a = (*m1).borrow_mut() ;
                *a = PDPStatus::b;
                println!("a");},
            b=> {let m1 = self.pdp_state.clone();m1.replace( PDPStatus::a);
                println!("b");},
        };

    }
}
fn main() {
    let mut network1 = network::new();
    network1.set();
    network1.set();
    network1.set();
    network1.set();
}

Update: My set function would look like this. I need two closure that have access to pdp_state. I pass these closures as callbacks. I am sure the these closure wouldn't call together.

    fn set(&mut self){
        let borrowed_pdp_status = self.pdp_state.borrow().clone();
        match borrowed_pdp_status {
            PDPStatus::a => {
                let mut state = self.pdp_state.clone();
                let mut closuree = || state =  Rc::new(RefCell::new(PDPStatus::b));
                let mut state1 = self.pdp_state.clone();
                let mut closuree1 = || state1 = Rc::new(RefCell::new(PDPStatus::b));

                closuree();
                closuree1();
                println!("a");
            },
            PDPStatus::b => {
                let mut closuree = || self.pdp_state = Rc::new(RefCell::new(PDPStatus::a));
                closuree();
                println!("b");
            },
        };
    }

In the set method, you need to borrow self.pdp_state and then clone() it in a variable, and then match the variable where you cloned it.

Replace the set method with this:

fn set(&mut self) {
        let borrowed_pdp_status = self.pdp_state.borrow().clone();
        match borrowed_pdp_status {
            PDPStatus::a => {
                self.pdp_state = Rc::new(RefCell::new(PDPStatus::b));
                println!("a");
            },
            PDPStatus::b => {
                self.pdp_state = Rc::new(RefCell::new(PDPStatus::a));
                println!("b");
            },
        };
}

Playground link - https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=426d4cb7db9a92ee4ddcd4f36dbc12f7

This answer was posted after the question was updated:

EDIT

You can use the replace() method from RefCell

fn set(&mut self) {
    let borrowed_pdp_status = self.pdp_state.borrow().clone();
    match borrowed_pdp_status {
        PDPStatus::a => {
            let mut closuree = || {
                self.pdp_state.replace(PDPStatus::b);
            };
            let mut closuree1 = || {
                self.pdp_state.replace(PDPStatus::b);
            };

            closuree();
            closuree1();
            println!("a");
        }
        PDPStatus::b => {
            let mut closuree = || {
                self.pdp_state.replace(PDPStatus::a);
            };
            closuree();
            println!("b");
        }
    };
}

Playground link - https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=4af02228d58b2f2c865a525e3f70d6a0

OLD

You could just make the closures take &mut self.pdp_state as an argument, and then update it.

fn set(&mut self) {
    let borrowed_pdp_status = self.pdp_state.borrow().clone();
    match borrowed_pdp_status {
        PDPStatus::a => {
            let mut closuree = |local_pdp_state: &mut Rc<RefCell<PDPStatus>>| {
                *local_pdp_state = Rc::new(RefCell::new(PDPStatus::b))
            };
            let mut closuree1 = |local_pdp_state: &mut Rc<RefCell<PDPStatus>>| {
                *local_pdp_state = Rc::new(RefCell::new(PDPStatus::b))
            };

            closuree(&mut self.pdp_state);
            closuree1(&mut self.pdp_state);
            println!("a");
        }
        PDPStatus::b => {
            let mut closuree = |local_pdp_state: &mut Rc<RefCell<PDPStatus>>| {
                *local_pdp_state = Rc::new(RefCell::new(PDPStatus::a))
            };
            closuree(&mut self.pdp_state);
            println!("b");
        }
    };
}

Playground link - https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=4af96385b0446082afdb7d615bb8eecb

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM