data-structures - 如何断言/内省(introspection)嵌套的递归结构/枚举?

标签 data-structures rust enums nested

我有一个有向图数据结构,我发现自己在与模式匹配作斗争以进行简单的内省(introspection)。有没有更好的办法?
除了多个 child 之外,我的结构还允许多个 parent :

pub enum NodePtr {
    Terminal(i32),
    Node(Rc<RefCell<Node>>),
}

pub struct Node {
    children: Vec<NodePtr>,
    parents: Vec<Weak<RefCell<Node>>>,
}
这是我可以设计的最简单的代码来断言已按预期建立了单个父子关系:
fn example(parent: NodePtr, child: NodePtr) {
    if let NodePtr::Node(parent_rc) = &parent {
        if let NodePtr::Node(child_rc) = &child {
            assert_eq!(parent_rc.borrow().children.len(), 1);
            if let Option::Some(node_ptr) = parent_rc.borrow().children.get(0) {
                if let NodePtr::Node(rc) = node_ptr {
                    assert!(Rc::ptr_eq(rc, child_rc));
                } else {
                    assert!(false);
                }
            } else {
                assert!(false);
            }

            assert_eq!(child_rc.borrow().parents.len(), 1);
            if let Option::Some(weak) = child_rc.borrow().parents.get(0) {
                if let Some(rc) = weak.upgrade() {
                    assert!(Rc::ptr_eq(&rc, parent_rc));
                } else {
                    assert!(false);
                }
            } else {
                assert!(false);
            }
        } else {
            assert!(false);
        }
    } else {
        assert!(false)
    };
}
Full working example
感觉就像我必须经历这么多匹配才能得到我想要的。我是否错过了更好的方式或不同的思维方式?

最佳答案

It feels like I have to wade through so much matching to get at what I want. Am I missing some better way or perhaps a different way of thinking?


您可以在实用函数后面抽象出琐碎的模式匹配,例如:
impl NodePtr {
    /// Returns Some if NodePtr is a Node, None otherwise.
    fn as_node(&self) -> Option<&Rc<RefCell<Node>>> {
        match self {
            NodePtr::Node(rc) => Some(rc),
            _ => None,
        }
    }
}
这允许您替换 if let NodePtr::Node(foo) = foo { ... } else { assert!(false); }let foo = foo.as_node().unwrap() .您也可以使用foo.unwrap()而不是整个 if let Some(foo) = foo { ... } else { assert!(false); }堵塞。最后,您不需要对 x.get(n) 进行模式匹配。 , 你可以使用 x[n]&x[n] .
应用所有这些会将您的代码压缩为以下内容:
// prove parent & child relationship
let parent_rc = parent.as_node().unwrap();
let child_rc = child.as_node().unwrap();
assert_eq!(parent_rc.borrow().children.len(), 1);
let node_ptr = &parent_rc.borrow().children[0];
assert!(Rc::ptr_eq(node_ptr.as_node().unwrap(), child_rc));
assert_eq!(child_rc.borrow().parents.len(), 1);
let weak = &child_rc.borrow().parents[0];
assert!(Rc::ptr_eq(&weak.upgrade().unwrap(), parent_rc));
Playground
还有一个单独的问题是,您的类型是否可以被结构化以避免如此多的运行时检查和 panic 的可能性。我建议查看现有的 crate 以构建 DAG。

关于data-structures - 如何断言/内省(introspection)嵌套的递归结构/枚举?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64848101/

相关文章:

error-handling - 如何返回带有一般错误的结果

rust - 如何解决为什么 cargo/rustc 链接在 rust 标准库符号中,即使使用了 no_std?

c++ - 如何在 C++11 中处理弱枚举的 `using`?

enums - Angular2 - 类型 'object' 不可分配给类型 'enum'

javascript - 根据数组元素从数组中提取元素

ios - 如何在 Objective-C 中表示表格数据

rust - A 型或 B 型都使用rust

Typescript 有联合,那么枚举是多余的吗?

scala - 表示区间映射的数据结构

java - 使用泛型定义 HashMap 的递归定义