Допустим, у нас есть некая рекурсивная структура. Например, n-арное дерево:
enum Tree<'a> {
Leaf(i32),
Node(Vec<&'a Tree<'a>>)
}
Допустим, мы хотим метод для получения самого левого потомка и хотим реализовать его нерекурсивно:
impl<'a> Tree<'a> {
fn leftmost(&self) -> &'a Tree {
let mut leftmost = self;
while let Tree::Node(ref children) = *leftmost {
leftmost = children[0]
}
leftmost
}
}
Проверяем:
fn main() {
let bottom = Tree::Leaf(42);
let middle = Tree::Node(vec![&bottom]);
let top = Tree::Node(vec![&middle]);
if let Tree::Leaf(val) = *top.leftmost() {
println!("val: {}", val)
}
}
Печатает val: 42
, как и ожидается.
Теперь мы хотим сделать так, чтобы на одного потомка произвольной вершины могли ссылаться несколько слотов родительской вершины, т. е. чтобы потомок был достижим разными путями. Поскольку нам нужно много ссылок на одно значение, нам нужен Rc<Tree>
. Поскольку Rc
неизменяем, нам нужен Rc<RefCell<Tree>>
:
enum RCTree {
Leaf(i32),
Node(Vec<Rc<RefCell<RCTree>>>)
}
leftmost
:
impl RCTree {
fn leftmost(&self) -> &RCTree {
let mut leftmost = self;
while let RCTree::Node(ref children) = *leftmost {
// &Ref<RCTree> coerces to &RCTree
leftmost = &children[0].borrow()
}
leftmost
}
}
rustc 1.12.1 (d4f39402a 2016-10-19) error: borrowed value does not live long enough --> <anon>:29:19 | 29 | leftmost = &children[0].borrow() | ^^^^^^^^^^^^^^^^^^^^ | note: reference must be valid for the anonymous lifetime #1 defined on the block at 25:32... --> <anon>:25:33 | 25 | fn leftmost(&self) -> &RCTree { | ^ note: ...but borrowed value is only valid for the expression at 27:53 --> <anon>:27:54 | 27 | while let RCTree::Node(ref children) = *leftmost { | ^ error: aborting due to previous errorВопрос: можно ли реализовать таким образом
leftmost
для RCTree
и если можно, то как?