如何结合枚举变量和值的测试?

Nat*_*dge 5 enums rust

在 Rust 中,假设我有一个枚举,我想根据它的变体和一些涉及它的值的测试做一些有条件的事情。我很难找到写这个的好方法。

例如,假设我有一个枚举来表示农场动物,变体给出了它们的物种,而值给出了一些其他属性,例如它们的重量。

enum Animal {
    Horse(i32),
    Cow(i32, i32),
    Sheep,
    // and so on
}
Run Code Online (Sandbox Code Playgroud)

我想要一个喂养动物的功能。大多数动物都吃干草,但体重低于 700 公斤的马却吃胡萝卜。

直觉上我想写

fn feed(animal: Animal) {
    if let Animal::Horse(weight) = animal && weight < 700 { // ferris_is_confused.png
        // feed carrots
    } else {
        // feed hay
    }
}
Run Code Online (Sandbox Code Playgroud)

但我得到编译错误“let这个位置的表达式是实验性的”和“预期的表达式,找到的语句(let)”。

我可以写

fn feed(animal: Animal) {
    if let Animal::Horse(weight) = animal {
        if weight < 700 {
            // feed carrots
        } else {
            // feed hay
        }
    } else {
        // feed hay
    }
}
Run Code Online (Sandbox Code Playgroud)

但随后我必须复制// feed hay代码,如果代码很长或经常更改,这可能会出现问题。

我有同样的问题,如果我使用match:我可以把一个测试if weight < 700里面Horse手臂,但后来我又必须包括// feed hay在其else以及在_手臂。

是否有一种标准的惯用方式来编写它而不复制代码?这可能是一个常见问题,但我可能正在搜索错误的术语。

我正在使用 rustc 1.46.0。

Flo*_*mer 4

比赛守卫已经存在了一段时间(Debian buster 的 1.34.2 已经有了它们)并以更简洁的方式支持这个用例:

fn feed(animal: Animal) {
   match animal {
     Animal::Horse(weight) if weight < 700 => {
       // feed carrots
     }
     _ => {
       // feed hay
     }
   }
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以将饲料干草部分移动到本地函数中并从多个位置调用它。