在Rust中如何引用匹配的值

13
假设我有这段代码:
fn non_zero_rand() -> i32 {
    let x = rand();
    match x {
        0 => 1,
        _ => x,
    }
}

有没有一种简洁的方法将 rand() 放入匹配中,然后将其绑定到一个值。例如,类似于这样的写法:

fn non_zero_rand() -> i32 {
    match let x = rand() {
        0 => 1,
        _ => x,
    }
}

或者也可以是:

fn non_zero_rand() -> i32 {
    match rand() {
        0 => 1,
        _x => _x,
    }
}

3
你的第二个例子应该能够正常工作。 - Lee
_x => _x 可以工作,但它在语义上不正确。前导下划线表示“此值未使用”,因此在这里不合适。 - Shepmaster
2个回答

28

如果一个match arm只包含一个标识符,那么它将匹配任何值,并声明一个以该标识符命名的变量,然后将该值移动到该变量中。例如:

match rand() {
    0 => 1,
    x => x * 2,
}

使用@模式创建并匹配变量的一种更通用的方式:

match rand() {
    0 => 1,
    x @ _ => x * 2,
}

在这种情况下不是必需的,但在处理条件匹配(如范围)时可能会很有用:

match code {
    None => Empty,
    Some(ascii @ 0..=127) => Ascii(ascii as u8),
    Some(latin1 @ 160..=255) => Latin1(latin1 as u8),
    _ => Invalid
}

1
x和未绑定的值是相同的,因此您应该只需使用x => x - Lee
1
@Lee 说得好。我扩展了答案,以展示更现实的 @ 模式用法。 - user4815162342
说句实话:这也有助于匹配多个模式,例如 token @ ( '{' | '}' | '(' | ')' ) => something_with(token) - dustypaws

3

你可以将模式绑定到名称:

fn non_zero_rand() -> i32 {
    match rand() {
        0 => 1, // 0 is a refutable pattern so it only matches when it fits.
        x => x, // the pattern is x here,
                // which is non refutable, so it matches on everything
                // which wasn't matched already before
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接