The goal here is to implement a basic binary tree with values only on leaves, with `depth`, `mirror`, and `in_order` (traversal) operations. I have not used Rust before. Some particular questions I have: * In a few places, I'm defining methods by passing `self` by reference and then matching on its derefenced form. I then have to borrow the fields with `ref` in the destructuring. Is this the intended form? * Is `into_in_order` using `Vec` properly/optimally? (I tried to use just `lv.extend(&mut rv)` but got an error that that particular method was still under churn and I should wait for "the dust to settle.") * Am I using `Box`es correctly? When should I use `Box`es vs. `* const`s? * Why do `(*r).mirror()` and `r.mirror()` do the same thing? I would have expected the latter to throw because `Box`es don't have a `mirror` method. * Is there a less verbose alternative to the `Branch(Box::new(Branch(…)))` syntax? <!-- x --> #[derive(Debug, PartialEq, Clone)] enum BTree<T> { Leaf(T), Branch(Box<BTree<T>>, Box<BTree<T>>), } impl <T> BTree<T> { fn depth(&self) -> i32 { match *self { BTree::Leaf(_) => 1, BTree::Branch(ref l, ref r) => std::cmp::max(l.depth(), r.depth()) + 1, } } fn into_in_order(self) -> Vec<T> { match self { BTree::Leaf(val) => vec!(val), BTree::Branch(l, r) => { let mut lv = l.into_in_order(); let rv = r.into_in_order(); lv.extend(rv.into_iter()); lv } } } } impl <T : Clone> BTree<T> { fn mirror(&self) -> BTree<T> { match *self { BTree::Leaf(_) => (*self).clone(), BTree::Branch(ref l, ref r) => BTree::Branch(Box::new((*r).mirror()), Box::new((*l).mirror())), // // why does this work? // BTree::Branch(Box::new(r.mirror()), Box::new(l.mirror())), } } } #[test] #[allow(unused_variables)] fn test_btree_creation() { use BTree::*; let leaf: BTree<i32> = Leaf(10); let branch: BTree<i32> = Branch(Box::new(Leaf(15)), Box::new(Leaf(20))); let tree: BTree<i32> = Branch(Box::new(branch.clone()), Box::new(Leaf(30))); assert_eq!(branch, branch.clone()); } #[test] fn test_btree_depth() { use BTree::*; assert_eq!(Leaf(10).depth(), 1); let branch: BTree<i32> = Branch(Box::new(Leaf(15)), Box::new(Leaf(20))); assert_eq!(branch.depth(), 2); let tree: BTree<i32> = Branch(Box::new(branch.clone()), Box::new(Leaf(30))); assert_eq!(tree.depth(), 3); let other_tree: BTree<i32> = Branch( Box::new(branch.clone()), Box::new(branch.clone())); assert_eq!(other_tree.depth(), 3); } #[test] fn test_btree_mirror() { use BTree::*; assert_eq!(Leaf(10).mirror(), Leaf(10)); assert_eq!( Branch(Box::new(Leaf(10)), Box::new(Leaf(20))).mirror(), Branch(Box::new(Leaf(20)), Box::new(Leaf(10)))); assert_eq!( Branch( Box::new(Leaf(10)), Box::new(Branch(Box::new(Leaf(20)), Box::new(Leaf(30)))) ).mirror(), Branch( Box::new(Branch(Box::new(Leaf(30)), Box::new(Leaf(20)))), Box::new(Leaf(10)))); } #[test] fn test_btree_in_order() { use BTree::*; assert_eq!(Leaf(10).into_in_order(), vec!(10)); assert_eq!(Branch(Box::new(Leaf(10)), Box::new(Leaf(20))).into_in_order(), vec!(10, 20)); assert_eq!( Branch( Box::new(Leaf(10)), Box::new(Branch(Box::new(Leaf(20)), Box::new(Leaf(30)))) ).into_in_order(), vec!(10, 20, 30)); } I also have the following macro definitions (not all used above): macro_rules! assert_eq { ($actual:expr, $expected:expr) => ( if $expected != $actual { panic!("expected {:?}, but got {:?}", $expected, $actual); } ) } macro_rules! assert_neq { ($actual: expr, $expected_not: expr) => ( if $expected_not == $actual { panic!("expected {:?} not to equal {:?}", $expected_not, $actual); } ) } macro_rules! assert_approx { ($actual: expr, $expected: expr) => { if ($expected - $actual).abs() > 1e-3 { panic!("expected {:?} or similar, but got {:?}", $expected, $actual); } } }