rust - 匹配子模式中的或运算符

标签 rust pattern-matching

rust documentation关于用于模式匹配的 | 运算符没有太多说明。只举了一个例子:

let x = 1;

match x {
    1 | 2 => println!("one or two"),
    3 => println!("three"),
    _ => println!("anything"),
}

the answer相反的this question ,我注意到以下编译:

struct S(E, usize);

#[derive(Copy, Clone)]
enum E {
    P(u8), Q(u8)
}

fn main() {
    let x = S(E::P(1), 10);
    if let S(E::P(..) | E::Q(..), _) = x {
        
    }
    
    let y = E::P(2);
    match (y, y) {
        (E::Q(..), E::P(..) | E::Q(..)) => {
            
        }
        _ => {}
    }
}

在该特定问题中,匹配的是整数,而不是枚举类型的值。整数实现了 std::ops::BitOr 特征,因此子模式会发生冲突。

我的问题是:

  1. 这是一项功能吗?为什么会编译?为什么它看起来有效?
  2. 此功能有哪些限制? (例如类型不得实现 BitOr 或类似的)
  3. 该功能叫什么?用于实现该功能的 AST 节点是什么?即使是编译器实现中 AST 节点类型的名称也比称为“|-operator”更好,因为它非常模糊。

最佳答案

Is this a feature? Why does it compile? Why does it seem to work?

在 Rust 1.53 之前,| 只允许在匹配臂的顶层,但从那时起它们被扩展为允许在嵌套模式中使用。所以你所看到的正在按预期工作;只是链接的问答已经过时了。


What are the limitations of this feature? (e.g. type must not implement BitOr or similar)

相反,这不使用 BitOr 运算符,因此适用于可以与多个值匹配的任何类型。请记住,模式匹配采用结构相等,而不是相等。因此,模式 1 | 2 将匹配 12,而如果它使用 BitOr 那么它只会匹配 3.

就功能而言,这是相当无限的:

Or-patterns are patterns that match on one of two or more sub-patterns (e.g. A | B | C). They can nest arbitrarily. Syntactically, or-patterns are allowed in any of the places where other patterns are allowed, with the exceptions of let-bindings and function and closure arguments. - Rust Reference


What is the feature called? What is the AST node used to implement the feature called? Even the name of the type of the AST node in the compiler implementation would be a better name to use in discussion than calling it the "|-operator", which is very vague.

原文RFC 2535简单地称为“或模式”,这反射(reflect)在引用文档中。不确定 AST 节点的名称,但 Pattern grammar Rust 引用中只是将 | 链直接作为 Pattern 生成的一部分,而其他类型的模式则推迟到 PatternNoTopAlt没有范围的模式

关于rust - 匹配子模式中的或运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72875966/

相关文章:

rust - 仅由不安全代码块组成的 Rust 函数是否有任何目的?

pattern-matching - Ocaml 中使用 try/with 语句进行类型检查?

performance - 转义下划线时 Postgres 索引行为不一致

pattern-matching - 通过功能组合来统一OCaml模式

scala - 通过与Array进行模式匹配进行的多重分配不适用于大写val

rust - 如何在 Rust 中写入最大缓冲区大小的格式化字符串?

rust - 参数位置中的 dyn Trait 是什么意思?

loops - 具有生命周期界限的递归函数内循环中的借用检查器错误

rust - 尝试在比赛中改变结构时借用检查器问题

f# - 与类型注释的模式匹配