我的树状结构如下:
use std::{cell::RefCell, collections::HashMap, rc::Rc};
struct Node<T> {
vals: HashMap<String, T>,
parent: Option<Rc<RefCell<Node<T>>>>,
}
这是一个链式哈希表:每个节点都包含一个哈希表和一个(可选的,因为树的根没有父级)共享指向其父级的指针。多个孩子可以共享同一个父母。
如果我想从链式哈希图中获取值的克隆,则可以使用递归在树上行走,就像这样:
impl<T> Node<T> {
pub fn get(&self, name: &str) -> Option<T> {
self.vals
.get(name)
.cloned()
.or_else(|| self.parent.as_ref().and_then(|p| p.borrow().get(name)))
}
}
但是,我需要对该树中包含的元素进行可变引用。由于我无法返回对元素的“标准”可变引用,因为它包含在RefCell,
中,所以我考虑过使用RefMut
和RefMut::map
函数来获取元素,如下所示:
use std::cell::RefMut;
impl<T> Node<T> {
pub fn get_mut<'a>(node: RefMut<'a, Node<T>>, name: &str) -> Option<RefMut<'a, T>> {
if node.vals.contains_key(name) {
Some(RefMut::map(node, |n| n.vals.get_mut(name).unwrap()))
} else {
node.parent.and_then(|p| Node::get_mut(p.borrow_mut(), name))
}
}
}
这不会编译:返回值引用其子节点(由于它也依赖于其子节点的借位),并且指向该子节点的RefMut
在函数出口处超出范围:
error[E0515]: cannot return value referencing function parameter `p`
--> src/lib.rs:16:31
|
16 | .and_then(|p| Node::get_mut(p.borrow_mut(), name))
| ^^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^^^^
| | |
| | `p` is borrowed here
| returns a value referencing data owned by the current function
error[E0507]: cannot move out of borrowed content
--> src/lib.rs:15:13
|
15 | node.parent
| ^^^^^^^^^^^ cannot move out of borrowed content
我不知道如何才能从这棵树中得到值得奉献的东西。我假设可能需要某种“ RefMut
链”以延长子节点RefMut
的生命周期,但是那样也不会创建对同一{的(组成)的多个可变引用) {1}}?
或者,是否有一种方法可以获取指向节点中值之一的某种Node
来避免这种依赖性链?我真的对要做的事情感到困惑。
请不要建议传递给给定名称的值而不是返回引用的函数,因为那不适用于我的用例:我真的只需要一个可变的引用(或使我可以获取的东西)一个。)
我不认为这是How do I return a reference to something inside a RefCell without breaking encapsulation?的副本,因为该答案仅涉及返回对单个Rc<RefCell>
中包含的值的组成部分的引用(我已经使用{ {1}})。我的问题涉及RefCell
链,该问题未解决。