In Rust, suppose I have an enum, and I'd like to do something conditional on its variant and some test involving its value. I'm having trouble finding a good way to write this.
For example, say I have an enum to represent farm animals, with the variant giving their species, and the value giving some other attributes such as their weight.
enum Animal {
Horse(i32),
Cow(i32, i32),
Sheep,
// and so on
}
I want a function to feed an animal. Most animals get hay, but a horse weighing under 700 kilos gets carrots instead.
Intuitively I want to write
fn feed(animal: Animal) {
if let Animal::Horse(weight) = animal && weight < 700 { // ferris_is_confused.png
// feed carrots
} else {
// feed hay
}
}
but I get compilation errors "let
expressions in this position are experimental" and "expected expression, found statement (let
)".
I can instead write
fn feed(animal: Animal) {
if let Animal::Horse(weight) = animal {
if weight < 700 {
// feed carrots
} else {
// feed hay
}
} else {
// feed hay
}
}
but then I have to duplicate the // feed hay
code, which could be problematic if it is long or changes frequently.
I have the same problem if I use match
: I can put a test if weight < 700
inside the Horse
arm, but then I again have to include // feed hay
in its else
as well as in the _
arm.
Is there a standard idiomatic way to write this without duplicating code? This might be an FAQ but I may be searching for the wrong terms.
I'm using rustc 1.46.0.
Match guards have been around for some time (Debian buster's 1.34.2 already has them) and support this use case in a less verbose fashion:
fn feed(animal: Animal) {
match animal {
Animal::Horse(weight) if weight < 700 => {
// feed carrots
}
_ => {
// feed hay
}
}
}
Alternatively, you can move the feed hay part into a local function and call that from multiple places.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With