Skip to content

Instantly share code, notes, and snippets.

@hucancode
Created September 15, 2023 02:33
Show Gist options
  • Save hucancode/882e6998950c9dac2461515612d32626 to your computer and use it in GitHub Desktop.
Save hucancode/882e6998950c9dac2461515612d32626 to your computer and use it in GitHub Desktop.
Learn RefCell with recursive struct
John: RefCell { value: Person { name: "John", partner: Some((Weak)) } }
John's partner: Some("Susan")
Susan: RefCell { value: Person { name: "Susan", partner: Some((Weak)) } }
Susan's partner: Some("John")
John's partner after dropping Susan:
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/main.rs:16:51
use std::{
cell::RefCell,
rc::{Rc, Weak},
};
#[derive(Debug)]
struct Person {
name: String,
partner: Option<Weak<RefCell<Person>>>,
}
impl Person {
fn partner_name(&self) -> Option<String> {
self.partner
.as_ref()
.map(|partner| Weak::upgrade(partner).unwrap())
.map(|partner| RefCell::borrow(&partner).name.clone())
}
}
pub fn main() {
let susan = Rc::new(RefCell::new(Person {
name: "Susan".to_string(),
partner: None,
}));
let john = Rc::new(RefCell::new(Person {
name: "John".to_string(),
partner: Some(Rc::downgrade(&susan)),
}));
// Now we can actually set them to be each other's partner:
RefCell::borrow_mut(&susan).partner = Some(Rc::downgrade(&john));
// Both `susan` and `john` are still accessible
println!("John: {:?}", john);
println!(
"John's partner: {:?}\n",
RefCell::borrow(&john).partner_name()
);
println!("Susan: {:?}", susan);
println!(
"Susan's partner: {:?}\n",
RefCell::borrow(&susan).partner_name()
);
// Note that `susan` and `john` do not keep each other alive, as they
// are only `Weak` references. Therefore dropping the `Rc` handle
// Will cause the `Weak` handle to lose the connection.
drop(susan);
println!("John's partner after dropping Susan:");
println!("{:?}", RefCell::borrow(&john).partner_name());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment