树模式匹配在 rust 给出奇怪的隐含错误

wi3ka0sx  于 2022-12-04  发布在  其他
关注(0)|答案(2)|浏览(145)

我不确定是什么地方出了问题:
我有一个枚举,如下所示:

#[derive(Debug,PartialEq)]
pub enum Tree {
    Leaf,
    Node(Box<Tree>,i32,Box<Tree>)
}

当我想求这棵树上所有叶子的总和时

pub fn tree_sum(t:&Tree) -> i32 {
    match t {
        Tree::Leaf => 0,
        Tree::Node(Leaf, x, Leaf) => *x

    }
}

编译器决定给予我一个非常奇怪的错误:

error[E0416]: identifier `Leaf` is bound more than once in the same pattern
  --> src/functions.rs:11:28
   |
11 |         Tree::Node(Leaf,x, Leaf) => *x,
   |                            ^^^^ used in a pattern more than once

有人能给我解释一下哪里出了问题,应该用什么来代替?

dphi5xsq

dphi5xsq1#

Tree::Node变量包含不是枚举的类型(Box<Tree>),这意味着您无法在内部变量上进行匹配。
这里发生的事情是,正如编译器告诉您的那样,您创建了两个具有相同名称的不同绑定。
如果我们假设您只对节点的内容感兴趣,您可以执行以下操作:

match t {
    Tree::Leaf => 0,
    Tree::Node(leaf1, x, leaf2) => ...
}

其中leaf1leaf2都是&Box<Tree>类型。
现在还不清楚match的目标是什么,如果你只对包含两个叶子的节点感兴趣,那么这将使match不是穷举的,你需要添加默认情况。
如果您对内部树的值不感兴趣,而只对*x感兴趣,则可以执行以下操作:

match t {
    Tree::Leaf => 0,
    Tree::Node(_, x, _) => *x,
}

这是详尽的。
如果你想匹配包含两个叶子的节点,那么你需要更有创造性。

match t {
    Tree::Leaf => 0,
    Tree::Node(leaf1, x, leaf2)
        if matches!(**leaf1, Tree::Leaf) && matches!(**leaf2, Tree::Leaf) =>
    {
        *x
    }
    Tree::Node(_, _, _) => todo!()
}

请注意,leaf1leaf2会被解除指涉两次才能解除boxed。这是必要的,因为t原本就是指涉。也需要预设的样式。
请在playground上查看。

gev0vcfq

gev0vcfq2#

Leaf是绑定到该枚举变量的一部分的变量的名称。您只需为Leaf选择一个不同的名称。

pub fn tree_sum(t:&Tree) -> i32 {
    match t {
        Tree::Leaf => 0,
        Tree::Node(Leaf, x, Leaf2) => *x
                          // ^^^ different name
    }
}

相关问题