我想将一个值与常数或其他值进行比较.用另一种语言(例如JavaScript),我会:

// Pretend these are values that are generated another way
let a = 23;
let b = 16;
let c = 43;
let input = 23;

switch (input) {
    case a: console.log("Input is equal to a"); break;
    case b: console.log("Input is equal to b"); break;
    case c: console.log("Input is equal to c"); break;
    default: console.log("Input does not equal any value"); break;
}

我该如何在Rust 的环境中干净利落地做到这一点?我知道我可以用if语句来实现,但我认为这很混乱,我正在与更多的值进行比较.

Can I compare a variable to constant values in Rust using a match statement?

推荐答案

做这种情况分析的最简单的方法是,当你事先知道这些 case 的价值时,不介意把它们放在代码的中间.在本例中,您需要一个简单的match表达式.

fn main() {
    for &input in &[16, 23, 42, 43] {
        match input {
            23 => println!("Input is equal to a"),
            16 => println!("Input is equal to b"),
            43 => println!("Input is equal to c"),
            _ => println!("Input does not equal any value"),
        }
    }
}

(playground link)

如果a bc是编译时常量(已知值或由const个函数生成),那么仍然可以直接匹配它们.

const A: i32 = 23;
const B: i32 = 16;
const C: i32 = generate_c();

const fn generate_c() -> i32 {
    A + B + 4
}

fn main() {
    for &input in &[16, 23, 42, 43] {
        match input {
            A => println!("Input is equal to a"),
            B => println!("Input is equal to b"),
            C => println!("Input is equal to c"),
            _ => println!("Input does not equal any value"),
        }
    }
}

(playground link)

然而,如果你try 使用非常量变量,你会得到奇怪的输出.

fn generate_c(a: i32, b: i32) -> i32 {
    a + b + 4
}

fn main() {
    let a = 23;
    let b = 16;
    let c = generate_c(a, b);

    for &input in &[16, 23, 42, 43] {
        match input {
            a => println!("Input is equal to a"),
            b => println!("Input is equal to b"),
            c => println!("Input is equal to c"),
            _ => println!("Input does not equal any value"),
        }
    }
}

(playground link)

如果你运行这个程序,编译器会给你很多关于"不可访问模式"的警告,并且四次输出都是"输入等于a".问题在于,match语句中每行的左侧不只是一个表达式,而是一个pattern.

模式是一个类似于(x, [_, z], Some(_))的表达式.它由基本变量(如xz)、下划线(_)、所有文字表达式(整数、浮点、元组、数组)和其他一些内容组成.

当Rust运行这样的匹配语句时,它会try 在语法上将输入与模式匹配.基本变量将匹配任何内容,并且该变量的值被设置为与match语句的该分支的范围匹配的任何内容.下划线(在上述所有示例中都使用)也匹配任何内容,但不绑定任何变量.

在上面的const版本中,代码中所有地方的常数ABC都被各自的文字值替换,因此输入与这些文字值匹配.

在变量版本中,当我们匹配a bc时,这些字母被解释为匹配任何东西的基本变量.模式中根本不考虑变量的值.在代码中

let a = 14;
let b = 15;
let c = 16;
let input = 16;
match input {
    a => println!("Input is equal to a"),
    b => println!("Input is equal to b"),
    c => println!("Input is equal to c"),
    _ => println!("Input does not equal any value"),
}

第一个分支将始终匹配,为输入提供分支范围的名称a.

如果需要匹配变量abc,可以 for each 分支添加一个保护.守卫通过为分支添加额外的条件来匹配,从而稍微过滤分支.在本例中,我们匹配任何内容并将其绑定到变量x,然后判断x是否等于a(以及bc).

fn generate_c(a: i32, b: i32) -> i32 {
    a + b + 4
}

fn main() {
    let a = 23;
    let b = 16;
    let c = generate_c(a, b);

    for &input in &[16, 23, 42, 43] {
        match input {
            x if x == a => println!("Input is equal to a"),
            x if x == b => println!("Input is equal to b"),
            x if x == c => println!("Input is equal to c"),
            _ => println!("Input does not equal any value"),
        }
    }
}

(playground link)

这比switch/case构造要详细一点,但我希望它清楚地说明了发生了什么.在每个分支上,变量x都被绑定到16,如果这等于变量A(或BC),则该分支被接受.否则,我们try 下一个分支.

Rust相关问答推荐

为什么父作用域中的变量超出了子作用域

是否可以为`T:Copy`执行`T. clone`的测试

从Rust调用C++虚拟方法即使在成功执行之后也会引发Access违规错误

如何使用Match比较 struct 中的值

值为可变对象的不可变HashMap

如何使用 list 在Rust for Windows中编译?

在Rust中有没有办法在没有UB的情况下在指针和U64之间进行转换?

为什么这个变量不需要是可变的?

变量需要parse()中的显式类型

用于判断整数块是否连续的SIMD算法.

如何创建一个可变的嵌套迭代器?

为什么 Rust 创建的 f32 小于 f32::MIN_POSITIVE?

使用 pyo3 将 Rust 转换为 Python 自定义类型

使用占位符获取用户输入

如何在 Rust 中将函数项变成函数指针

bcrypt 有长度限制吗?

通用函数中的生命周期扣除和borrow (通用测试需要)

如何从 Rust 中不同类型的多个部分加入 Path?

如何在 Rust 的内置函数上实现特征?

如何迭代调用可能会失败的函数?操作员?