在Rust中,假设我有一个枚举,我想根据它的变体和涉及它值的一些测试来做一些有条件的事情。我很难找到写这篇文章的好方法。
例如,假设我有一个枚举来表示农场动物,变体给出了它们的物种,值给出了一些其他属性,比如它们的重量。
enum Animal {
Horse(i32),
Cow(i32, i32),
Sheep,
// and so on
}
我想要一个喂养动物的功能。大多数动物都吃干草,但体重低于700公斤的马却吃胡萝卜。
凭直觉我想写
fn feed(animal: Animal) {
if let Animal::Horse(weight) = animal && weight < 700 { // ferris_is_confused.png
// feed carrots
} else {
// feed hay
}
}
但是我得到了编译错误";在这个位置上的CCD_ 1表达是实验性的;以及";期望的表达式,找到的语句(let
(";。
我可以写
fn feed(animal: Animal) {
if let Animal::Horse(weight) = animal {
if weight < 700 {
// feed carrots
} else {
// feed hay
}
} else {
// feed hay
}
}
但我必须复制// feed hay
代码,如果它很长或频繁更改,这可能会有问题。
如果我使用match
,我也会遇到同样的问题:我可以在Horse
臂中放入测试if weight < 700
,但之后我必须再次在其else
和_
臂中包含// feed hay
。
有没有一种标准的惯用方法可以在不重复代码的情况下编写这篇文章?这可能是一个常见问题,但我可能在搜索错误的术语。
我用的是rustc 1.46.0。
Match guards已经存在了一段时间(Debian buster的1.34.2已经有了它们(,并以一种不那么冗长的方式支持这个用例:
fn feed(animal: Animal) {
match animal {
Animal::Horse(weight) if weight < 700 => {
// feed carrots
}
_ => {
// feed hay
}
}
}
或者,您可以将feed hay部分移动到本地函数中,并从多个位置调用它。