我有一个使用Option,Rc和RefCell的链表排序结构。
我想为它实现fmt :: Debug,但是遇到了可爱的"无法摆脱借来的内容"错误。
use std::fmt;
use std::rc::{Rc, Weak};
use std::cell::RefCell;
#[derive(Clone, Debug, Ord, Eq, PartialOrd, PartialEq)]
struct NodeId {id: String}
impl NodeId {
pub fn new(s: &str) -> NodeId { NodeId{id: s.to_string()}}
}
struct NodeInfo {
nodeid: NodeId,
prev: Option<Rc<RefCell<NodeInfo>>>,
next: Option<Rc<RefCell<NodeInfo>>>,
}
impl fmt::Debug for NodeInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "NodeInfo( {} {} {} )", self.nodeid.id,
match self.prev { None => "none".to_string(), Some(ref n) => n.borrow().nodeid.id},
match self.next { None => "none".to_string(), Some(ref n) => "some".to_string()},
)
}
}
fn main() {}
理想情况下,调试输出可以显示.next和.previous节点的ID。但Rust不允许访问它们。尝试.borrow()RefCell的内容会导致错误,但我无法理解为什么。
在此播放:http://is.gd/Sah7sT
答案 0 :(得分:3)
要扩展@ Shepmaster的答案(绝对正确),您可以避免在这种情况下复制字符串,方法是将子节点的id直接写入格式化程序。
我选择使用新类型来避免重复:
impl fmt::Debug for NodeInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "NodeInfo( {} {:?} {:?} )", self.nodeid.id, ChildNode(&self.prev), ChildNode(&self.next))
}
}
struct ChildNode<'a>(&'a Option<Rc<RefCell<NodeInfo>>>);
impl<'a> fmt::Debug for ChildNode<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self.0 {
Some(ref n) => write!(f, "{}", n.borrow().nodeid.id),
None => write!(f, "None"),
}
}
}
答案 1 :(得分:2)
RefCell :: borrow()是否会移动内容?
没有。把它称为借用并让它移动将是非常卑鄙的! ^ _ ^
问题在于您试图将id
移出借来的结构。这是一个举措,因为String
不是Copy
:
n.borrow().nodeid.id
相反,使用clone
将当前字符串保留在原来的位置,然后返回一个全新的字符串:
n.borrow().nodeid.id.clone()