Skip to content

Instantly share code, notes, and snippets.

@piboistudios
Forked from rust-play/playground.rs
Last active December 31, 2023 14:15
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save piboistudios/c8db0e9b25efbcd5fa22c53e3db89780 to your computer and use it in GitHub Desktop.
Save piboistudios/c8db0e9b25efbcd5fa22c53e3db89780 to your computer and use it in GitHub Desktop.
[RUST]Parent-Children Tree (#2)
// we will use weak references with the Rc<T> (reference counting pointer) type
// weak references allow us to make references to a value that will -not- keep it alive
// this is perfect in the intsance of children, as we will soon see
use std::rc::{Rc,Weak};
use std::cell::RefCell;
// this example builds upon the last by storing a vector of children as well as a parent
#[derive(Debug)]
struct Node {
value: i32,
// you may ask why exactly we are mutating immutable data as opposed to just using &Weak<Node>
// the answer is lifetimes :)
parent: RefCell<Weak<Node>>,
children: RefCell<Vec<Rc<Node>>>,
}
fn main() {
// lets create the child first
let leaf = Rc::new(Node {
value: 3,
// recall that we must use associated functions to get the appropriate pointer types
children: RefCell::new(vec![]),
// even the Weak pointer has an associated new() fn
parent: RefCell::new(Weak::new()),
});
println!( // print out the strong and weak reference counts for the leaf, they should equal 1 and 0
"leaf strong = {} weak = {}",
Rc::strong_count(&leaf),
Rc::weak_count(&leaf)
);
{ // create a new scope within our main function
let branch = Rc::new(Node{ // create a branch where the previously created leaf is our child
value:5,
children: RefCell::new(vec![Rc::clone(&leaf)]),
parent: RefCell::new(Weak::new()),
});
// 1. borrow a mutable reference of the leaf's parent
// 2. dereference it
// 3. set it equal to a weak reference to the branch node
*leaf.parent.borrow_mut() = Rc::downgrade(&branch);
println!(// print branch ref counts
"branch strong = {} weak = {}",
Rc::strong_count(&branch),
Rc::weak_count(&branch),
);
println!( // print leaf ref counts
"leaf strong = {} weak = {}",
Rc::strong_count(&leaf),
Rc::weak_count(&leaf)
);
// we can tell that weak referencing works because this actually can print out the parent
// whereas before when we tried printing an object(1) with a reference to an object(2) that holds a reference to
// the original object(1) (recall this is what we did in the Cons-List exercise
println!("leaf parent = {:#?}", leaf.parent.borrow().upgrade());
} // parent goes out of scope even though the child has a reference to it
// the parent now equals None! it's gone out of scope even though we had a reference to it!
// println!("leaf parent = {:#?}", leaf.parent.borrow().upgrade());
println!( // print ref counts
"leaf strong = {} weak = {}",
Rc::strong_count(&leaf),
Rc::weak_count(&leaf),
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment