RefCell ::借用移动内容吗?

时间:2015-02-07 03:42:05

标签: rust

我有一个使用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

2 个答案:

答案 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()