Rust中有传统的样式切换语句吗?

问题描述 投票:-1回答:1

我想将值与常量或其他值进行比较。在另一种语言(例如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语句来做,但我认为这很麻烦,而且我正在与更多的值进行比较。

我可以使用match语句将Rust中的变量与常量值进行比较吗?

rust
1个回答
4
投票

进行此类案例分析的最简单方法是事先知道案例的值,并且不介意将它们放在代码中间。在这种情况下,一个简单的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)

但是,如果您使用非常量变量进行尝试,则会得到奇怪的输出。

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)

如果你运行它,编译器会给你很多关于“无法访问的模式”的警告,输出将是“输入等于一个”四次。这个问题是匹配语句中每一行的左侧不仅仅是一个表达式,而是一个模式。

模式是像(x, [_, z], Some(_))这样的表达。它是由基本变量(如xz),下划线(_),所有文字表达式(整数,浮点数,元组,数组)和其他一些东西构建的。

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

使用上面的const版本,常量A BC将替换为代码中各处的各自的字面值,因此输入在这些文字值上匹配。

对于变量版本,当我们与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

如果你需要匹配变量a bc,你可以为每个分支添加一个守卫。保护通过为要匹配的分支添加附加条件来过滤分支。在这种情况下,我们匹配任何东西并将其绑定到变量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)

这比开关/外壳结构稍微冗长一点,但我希望很明显发生了什么。在每个分支处,变量x绑定到16,然后如果它等于变量A(或BC),则采用该分支。否则,我们尝试下一个分支。

© www.soinside.com 2019 - 2024. All rights reserved.