I am trying to create the structure for an expression tree in rust, and I'd like for it not just to work, but also be efficient (Thus the usage of ids and an array instead of walking through pointers) and also simple to create (As in, I don't want the code for a new tree to be excessively verbose).
Currently, I have something like so:
#[derive(Debug, Default)]
struct ExprTree {
tree: Vec<Node>,
}
#[derive(Debug)]
struct Node {
index: usize,
content: String,
lhs: Option<usize>,
rhs: Option<usize>,
}
impl Node {
fn new(id: usize, content: &str, lhs: Option<usize>, rhs: Option<usize>) -> Self {
Self {
index: id,
content: content.to_string(),
lhs: lhs,
rhs: rhs
}
}
}
impl ExprTree {
fn new() -> Self {
Self {
tree: Vec::new()
}
}
fn new_expr(&mut self, content: &str, lhs: Option<usize>, rhs: Option<usize>) -> usize {
let id = self.tree.len();
self.tree.push(Node::new(id, content, lhs, rhs));
return id;
}
}
With the idea being that for an expression of the form "(name == Alice) && (age >= 30)" I can define a tree like so:
fn main() {
let mut tree = ExprTree::new();
tree.new_expr(
"&&",
Some(tree.new_expr(
"==",
Some(tree.new_expr("name", None, None)),
Some(tree.new_expr("Alice", None, None)),
)),
Some(tree.new_expr(
">=",
Some(tree.new_expr("age", None, None)),
Some(tree.new_expr("30", None, None)),
)),
);
}
This structure does what I want it to do: it should be very fast to traverse using a stack of ints and the code around it isn't too verbose. The problem is, I did this like I would in C++, and Rust doesn't allow me to do it, saying 'cannot borrow tree
as mutable more than once at a time'
My questions are: Why can't I do this? I'm mutating the Vec
inside of the tree, not the tree itself, so I don't really understand why this happens. How would I go about making this work?
Also, in a more general sense, is there a better/more accepted way of doing trees in rust?