Current best practice for parent/child struct relationship

Hi,

I have found a number of solutions or workarounds for this common use case, but most seem to be either quite old, or overly complex. I was wondering if there had been any movement in this area and what the current best practices for idiomatic Rust would be.

Basically I have a struct of type X that has a vector of struct 'Y'. In struct 'Y' I have some local configuration information, but should that information be missing, I'd want to use the configuration of the parent struct 'X'.

What is the current best practice for this sort of relationship?

Thanks in advance! :slightly_smiling_face:

The most immediate solution would be:

struct Node {
    children: Vec<Rc<Node>>,
    parent: Weak<Node>,
}

Note however that this might not be the easiest to use, specifically if you need to mutate the nodes.

1 Like

Just slight adjustment, to allow mutating:

struct Node {
    children: Vec<Rc<RefCell<Node>>>,
    parent: Weak<Node>,
}

Thanks!

I'll give that a go :slight_smile:

The structure is immutable, so I could actually just add duplicate entries if all else fails - it just seems like a better idea to use something like Weak :slight_smile:

I'd avoid the Rc<_> approach. For one, you can easily introduce reference cycles if you aren't careful, and letting the child has some sort of reference back to its parent muddies the ownership story (as evidenced by the need to use RefCell for mutation).

Instead, make the "I might need a default value" requirement explicit when trying to access the child's value.

struct Parent {
  children: Vec<Child>,
  default_value: f64,
}

struct Child {
  value: Option<f64>,
}

impl Child {
  fn get_value(&self, default: f64) -> f64 {
    match self.value {
      Some(v) => v,
      None => default,
    }
  }
}

Then, you'd use it like this:

let parent = Parent { ... };

for child in &parent.children {
  let value = child.get_value(parent.default_value);
  ...
}
2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.