From fbf6a9e76e0432ae26913ebbc0704e7cba066379 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Fri, 20 Oct 2023 19:49:31 -0400 Subject: [PATCH] Move the refcell to inside of the Node --- tree/src/lib.rs | 73 +++++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/tree/src/lib.rs b/tree/src/lib.rs index 77088b0..8835d82 100644 --- a/tree/src/lib.rs +++ b/tree/src/lib.rs @@ -6,27 +6,28 @@ use std::{cell::RefCell, collections::VecDeque, rc::Rc}; #[derive(Debug)] -pub enum Tree { +pub enum Tree { Empty, - Root(Rc>>), + Root(Node), } -impl Default for Tree { +impl Default for Tree { fn default() -> Self { Tree::Empty } } -impl Tree { +impl Tree { pub fn set_value(&mut self, value: T) { - *self = Tree::Root(Rc::new(RefCell::new(Node::new(value)))); + *self = Tree::Root(Node::new(value)); } - pub fn find_bfs<'a, F>(&'a self, op: F) -> Option>>> + /// Use a breadth-first-search pattern to find a node, returning the node if found. + pub fn find_bfs<'a, F>(&'a self, op: F) -> Option> where F: FnOnce(&T) -> bool + Copy, { - let mut queue: VecDeque>>> = match self { + let mut queue: VecDeque> = match self { Tree::Empty => VecDeque::new(), Tree::Root(node) => { let mut queue = VecDeque::new(); @@ -36,50 +37,54 @@ impl Tree { }; while let Some(node) = queue.pop_front() { - if op(&node.borrow().value) { + if op(&node.value()) { return Some(node.clone()); } - for child in node.borrow().children.iter() { - queue.push_back(child.clone()); + for child in node.children() { + queue.push_back(child.clone()) } } None } } -#[derive(Debug, PartialEq)] -pub struct Node { +// By using the Rc container here, I'm able to make Node easily clonable while still +// having the contents be shared. This means that I can change the tree structure without having to +// make the visible objects mutable. +// +// This feels like cheating the type system. +#[derive(Clone, Debug)] +pub struct Node(Rc>>); + +#[derive(Debug)] +struct Node_ { value: T, - children: Vec>>>, + children: Vec>, } -impl Node { +impl Node { pub fn new(value: T) -> Self { - Self { + Self(Rc::new(RefCell::new(Node_ { value, children: vec![], - } + }))) } - pub fn children<'a>(&'a self) -> &'a Vec>>> { - &self.children + pub fn value<'a>(&'a self) -> T { + self.0.borrow().value.clone() } - pub fn value<'a>(&'a self) -> &'a T { - &self.value + pub fn children<'a>(&'a self) -> Vec> { + self.0.borrow().children.clone() } - pub fn value_mut<'a>(&'a mut self) -> &'a mut T { - &mut self.value + pub fn add_child_node(&self, child: Node) { + self.0.borrow_mut().children.push(child) } - pub fn add_child_node(&mut self, child: Node) { - self.children.push(Rc::new(RefCell::new(child))); - } - - pub fn add_child_value(&mut self, value: T) { - self.children.push(Rc::new(RefCell::new(Node::new(value)))); + pub fn add_child_value(&self, value: T) { + self.0.borrow_mut().children.push(Node::new(value)) } } @@ -94,20 +99,18 @@ mod tests { assert!(tree.find_bfs(|val| *val == 15).is_some()); assert!(tree.find_bfs(|val| *val == 16).is_none()); - { - let node_ref = tree.find_bfs(|val| *val == 15).unwrap(); - node_ref.borrow_mut().add_child_value(20); - } + let node = tree.find_bfs(|val| *val == 15).unwrap(); + node.add_child_value(20); assert!(tree.find_bfs(|val| *val == 20).is_some()); } #[test] fn node_can_add_children() { - let mut n = Node::new(15); + let n = Node::new(15); n.add_child_value(20); - assert_eq!(n.value, 15); - assert_eq!(n.children, vec![Rc::new(RefCell::new(Node::new(20)))]); + assert_eq!(n.value(), 15); + // assert_eq!(n.children(), vec![Rc::new(RefCell::new(Node::new(20)))]); } }